장고에서 기본적으로 제공해주는 forms에 대해 알아보자.
# new.html
{% extends 'base.html' %}
{% block content %}
<h1>New Blog Entry</h1>
<form action="{%url 'blog:create'%}" method="post" enctype="multipart/form-data">
{%csrf_token%}
<p>제목: <input type="text" name="title"></p>
<p>작성자: <input type="text" name="writer"></p>
<p>사진: <input type="file" name="image" /></p>
<p>본문: <br><textarea name="body" id="" cols="30" rows="10"></textarea><br></p>
<button type='submit'>작성하기</button>
</form>
{% endblock %}
지금까지는 위와 같이 <form></form>
내부에 필요한 input 값들을 일일이 추가해서 필요한 데이터들을 사용자로부터 받아왔다.
허나 장고에서는 이러한 것들을 쉽고 빠르게 구현할 수 있게 해주는 기능을 제공한다. 이를 통해 우리는 크게 두 가지 장점을 얻을 수 있다.
# forms.py (app폴더(blog) 안에서!)
from django import forms # 장고가 제공해주는 form라이브러리
from .models import Blog
class BlogForm(forms.ModelForm):
class Meta:
model = Blog
fields = ['title','writer','body', 'image']
forms.ModelForm
의 기능을 형식에 맞춰 사용한다는 정도로 이해하자.fields = ['title', 'writer', 'body', 'image']
를 설정 해주는 것이다.장고에서 클래스를 정의할 때 내부 클래스로 사용되어 상위 클래스에게 meta data를 제공합니다. meta data란 쉽게 말해서 '데이터에 대한 데이터' 혹은 '다른 데이터를 설명해주는 데이터'라고 생각하시면 됩니다.
Meta 클래스에 대한 구체적인 내용은 공식 문서 를 참고해주세요!
# new_with_django_form.html
{% extends 'base.html' %}
{% block content %}
<h1>New Blog Entry</h1>
<form
action="{%url 'blog:create'%}"
method="post"
enctype="multipart/form-data"
>
{%csrf_token%}
{{form.as_p}}
</form>
{% endblock %}
new_with_django_form.html로 이름을 설정해 둔 것은 앞서 작성한 new.html의 코드들을 남겨두기 위함이다.
장고 form을 사용하는 방법은 다양하게 있다.
form.as_table
, form.as_p
, form.as_ul
등 다양하게 있으나 주로 form.as_table
과 form.as_p
를 가장 많이 사용한다.form.as_table
: 각각의 input 태그를 tr 태그로 감싸서 반환form.as_p
: 각각의 input 태그를 p 태그로 감싸서 반환form.as_ul
: 각각의 input 태그를 li 태그로 감싸서 반환 코드를 작성하기 앞서 forms.py
에서 작성한 BlogForm 클래스를 사용하기 위해서 상단에 import를 해주자.
# views.py
# 이전 코드들..
from .forms import BlogForm # <--- BlogForm을 사용해야 하니 import를 해줍시다.
def new_with_django_form(request):
form = BlogForm()
return render(request, 'new_with_django_form.html', {'form': form})
VS
def new(request):
return render(request, 'new.html')
def create_with_django_form(request):
form = BlogForm(request.POST, request.FILES) # form 데이터를 처리하기 위해서 request.POST와 request.FILES가 필요함을 의미합니다.
if form.is_valid(): # 유효성 검사
new_blog = form.save(commit=False) # 임시 저장 나머지 필드(칼럼)를 채우기 위함
new_blog.pub_date = timezone.now()
new_blog.save()
return redirect('blog:detail', new_blog.id)
return redirect('home')
VS
def create(request):
new_blog = Blog()
new_blog.title = request.POST['title']
new_blog.writer = request.POST['writer']
new_blog.body = request.POST['body']
new_blog.image = request.FILES['image']
new_blog.pub_date = timezone.now()
new_blog.save()
return redirect('blog:detail', new_blog.id)
BlogForm
을 활용하여 new.html의 코드를 많이 줄일 수 있었다.BlogForm
을 활용하여 코드 길이를 줄였고, form.is_valid()
를 활용하여 사용자가 보낸 데이터의 유효성 검사도 할 수 있었다.view함수에서 CRUD 중 C, U의 경우 사용자가 어떠한 데이터를 보냈는지 검사하는것이 매우 중요합니다. 저희가 실습으로 진행해왔던 Blog 테이블은 title, writer, body가 빈칸으로 들어와서는 안되겠죠? 따라서 사용자가 보낸 데이터들을 검사 하는 것을 유효성 검사라고 합니다. 원래는 이러한 것들을(title은 몇자 이상, body는 몇자 이하 등등) view 함수 내에서 해줬어야 했는데 하지 않았습니다. 하지만 장고 form을 사용하게 되면 is_valid()를 통해 이를 쉽게 구현 할 수 있습니다.