python manage.py migratepython manage.py makemigrationsmigration 파일을 만듬migrate 명령어를 통해 이를 데이터베이스에 반영프로젝트를 만들고 최초로 runserver를 하면 다음과 같은 경고 메시지를 출력한다. 이는 초기값을 migrate하지 않아서 출력되는 메시지이다.
You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
models.py 에 다음과 같이 테이블 클래스를 생성한 뒤 migrate 하면 클래스에 대응되는 테이블이 DB에 생성된다.
속성이름 = models.데이터형식(제약조건)
class Blog(models.Model): # Model을 상속받음 --> 테이블을만들것이라는 것을 선언
title = models.CharField(max_length=200) # 제목.
body = models.TextField() # 본문
tag = models.CharField(max_length=50)
date = models.DateTimeField(auto_now_add=True) # 작성날짜 # 자동으로 지금 시간을 추가하겠다.
def __str__(self):
return self.title # 블로그
궁금한 점: 테이블 구조를 바꿀 때는 makemigrations 명령이 선행되어야 했지만, 인자값(eg. auto_now_add = True)를 바꾸는 것은 수정만으로도 변경사항이 적용되었다. 그 이뉴는 무엇인가?
테이블에 속성을 추가할 때는
makemigrations을 해야하지만 속성을 삭제할 때는 이 작업이 필요 없다. (내가 해봄)
makemigrations을 하면 다음과 같이 json형식의 파일이 생성된다.
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Blog',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=200)),
('body', models.TextField()),
('date', models.DateTimeField(auto_now_add=True)),
],
),
]
- Json형태로 저장됨.
- ID 속성이 primary key로서 자동으로 만들어짐.
- admin 사이트에서 우리가 만든 테이블 객체를 확인할 수 있음.
기존에 있던 테이블(클래스)에 새로운 속성을 추가하고 makemigrations을 하면 다음과 같은 경고?에러? 메시지가 발생한다.
It is impossible to add a non-nullable field 'tag' to blog without specifying a default. This is because the database needs something to populate existing rows.
Please select a fix:
1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
2) Quit and manually define a default value in models.py.
Select an option:
기존의 테이블에 새로운 속성을 추가하면 기존의 튜플들은 그 속성값을 부여받지 못했던 상태이다. 따라서 "기존의 튜플에 입력되는 기본값을 입력하라"는 메세지이다.
(populate: 덧붙이다, one-off: 단한번의)
makemigrations을 하면 다음과 같은 메시지가 프롬프트에 출력된다. 내가 어떤 작업을 수행했는지에 대해 꽤나 사용자친화적으로 출력해줌을 확인할 수 있다.
Migrations for 'blogapp':
blogapp/migrations/0002_blog_tag.py
- Add field tag to blog
blogapp/migrations/0003_remove_blog_tag.py
- Remove field tag from blog
'새 글 생성' a 태그를 타면 new.html로 넘어가서,input 태그나 textarea 태그에 정의된 폼에 제목과 본문을 작성할 수 있다. <form action="{% url 'create' %}" method="POST">
{% csrf_token %} <!-- 보안문제 해결 기능 토큰-->
<div>
<label for="title">제목</label><br/>
<input type="text" name="title" id="title">
</div>
<div>
<label for="body">본문</label><br/>
<textarea name="body" id="body" cols="30" rows="10"></textarea>
</div>
<input type="submit" value="글 생성하기">
</form>
메소드
form data가 서버로 제출될 때 사용되는 HTTP 메소드를 명시한다.
GET: 폼 데이터를 URL에 추가하여 전달
- 브라우저에 캐시되어 저장
- 보안상 취약점 존재
POST: 폼 데이터를 별도로 첨부하여 전달
GET 방식보다 보안성이 좋음액션
폼 데이터를 서버로 보낼 때 해당 데이터가 도착할 url
-submit 타입의 input 태그를 입력하면 /create 로 이동하고, 여기서는 create.html을 render하는 것이 아니라 새 글을 생성해주는 함수가 실행된다.
from django.shortcuts import render, redirect
from .models import Blog
from django.utils import timezone
def create(request): # 블로그 글을 저장해주는 함수 --> 앞선 함수와 성격이 다르다 (무언가를 보여줄_render_필요가 없음)
if(request.method=='POST'):
post = Blog() # Blog 객체 생성
post.title = request.POST['title']
post.body = request.POST['body']
post.tag = 0
post.date = timezone.now()
post.save() # 데이터베이스에 저장하는 함수(```insertSQL```을 수행)
return redirect('home') # 인자에 해당하는 URL로 HttpResponseRedirect 리턴
Redirect와 Render의 비교
render
요청한 페이지를 템플릿과 context를 결합하여 리턴
HttpResponse 객체를 리턴redirect
특정한 Url로 요청을 보냄
# forms.py에 정의
from django import forms
class Blogform(forms.Form):
# 내가 입력받고자 하는 값들
title = forms.CharField()
body = forms.CharField(widget=forms.Textarea)
def formcreate(request):
if request.method == 'POST':
# 입력 내용을 DB에 저장
form = Blogform(request.POST)
if form.is_valid(): # form이 유효한지 체크
post = Blog() # 튜플 생성
post.title = form.cleaned_data['title']
post.body = form.cleaned_data['body']
post.save()
return redirect('home')
else: # GET request
form = Blogform()
return render(request, 'form_create.html', {'form': form})
세번째 인자: form을 'form'이라는 이름으로 form_create.html에 보냄. html에서는 '{{ form }}' 으로써 사용 (as below)
<h1>django form을 이용한 새 글 작성 페이지</h1>
<form action="" method="POST">
{% csrf_token %}
<table>
{{ form.as_table}}
</table>
<input type="submit" value="새 글 생성하기">
</form>
{{form.as_table}}은 넘겨받은 form(tuple)을 table 형식으로 보여준다.
Modelform은 Form에 Model을 연결시킨 것이다.
forms.py에 다음과 같은 모델폼을 form의 Modelform을 상속받아 정의한다.
class BlogModelForm(form.Modelform):
class Meta:
model = Blog # models.py로부터 Blog객체를 import했기 때문에 가능
fields = ['title', 'body'] # 모든 ATTRBT을 포함하고 싶으면 '__all__'이라고 적음
views.py에서는 사용자가 request를 보냈을 때 처리할 함수를 정의한다.
def modelFormCreate(request):
if request.METHOD = 'POST':
form = BlogModelForm(request.POST)
if form.is_valid():
form.save()
return redirect('home')
else:
form = BlogModelForm()
return render(request, 'form_create.html', {'form':form})
1. 장고의 form으로부터 Modelform을 불러온다.
#
#
#
1. db로부터 블로그 객체를 가져오는 코드를 views.py로 가져와야 함.
1. rende
2. render의 세번째 인자로 index.html로 해당 객체를 보낼 수 있음
posts = Blog.objects.all() // 블로그 객체들이 모조리 가져와짐.
posts = Blog.objects.filter().order_by('-date')
return render(request , 'index.html', post)
<table>
{{ post }}
</table>
- 쿼리셋
- views.py가 db로부터 전달받은 객체들의 목록
- for문으로써 템플릿언어로써 객체 하나하나를 찍어줄것
{% for post in posts %}
{% endfor %}
detail/1, detail/2,....하나하나 html파일 만들어서 렌더링할꺼야?
index.html에는 다음과 같이 경로 지정
{% for post in posts %}
<a href="{% url 'detail' post.id %}"> {{post.id}
} {{ post.title}} </a>
{% endfor %}
'detail'외에 post.id 값이 추가적으로 필요
urls.py에는 다음과 같이 경로 지정
path('detail/<int:blog_id>', view.detail, name='detail'),
정수형 변수 blog_id(임의로 지정 가능)가 detail함수에 넘겨지게 됨
views.py에는 다음과 같이 detail함수 선언
from django.shortcuts import get_object_or_404
def detail(request, blog_id): # blog_id라는 추가적인 인자를 받음
# blog_id번째 블로그 글을 db로부터 가져와서
blog_detail = get_object_or_404(Blog, pk=blog_id) # 특정 개체 하나를 가져오는 메소드
# detail.html로 띄워주는 코드
return render(request, 'detail.html', {'blog_detail': blog_detail})
get_obeject_or_404함수는 blog_id를 pk로 가지는 Blog객체 '하나'를 반환하거나 없으면 404에러를 반환하는 함수
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL ='/media/'
urls.py에 경로 추가
or
+)
fron django.conf import settings
from django.conf.urls.static import static
--> 이해x 암기o
models.py안에 블로그 클래스 안에 사진을 추가학 ㅗㅅ피음
photo = models.ImageField(blank=True, null=True, upload_to='blog_photo')
객체가 바꼈으니 form도 바껴야함.