django-6. 폼(Form)

[Post:5.뷰] 에서 생성된 post를 보여주는 화면을 생성했다. 이제 화면에서도 post를 생성할 수 있게 만들자. django는 다른 어떤 프레임워크보다 편리한 폼제어를 할 수 있다. 개발자가 따로 어떠한 일을 하지 않아도 아래와 같은일을 알아서 해준다.

  • 데이터 준비 및 재구성 후 랜더링 준비
  • 데이터에 대한 html 양식 구성
  • 클라이언트로 부터 제출 된 양식 및 데이터 수신 및 처리

django Docs: working with forms


템플릿 생성 post_edit.html

{{form}} 인경우 그냥 랜더링 되지만, 옵션을 선택할 수 있음. {{ form.as_table }} table 셀로 wrap 됨. {{ form.as_p}} p 태그로 wrap {{ form.as_ul }} li 태그로 wrap

{% extends 'simple.html' %}
{% load staticfiles %}
{% block simpleContents %}
<link rel="stylesheet" href="{% static 'css/post.css' %}">
<p class="bar_title hidden">{{post.title}}(edit)</p>
<div class="post_box row" style="margin-top:50px;">
	<form method="POST" class="post-form"  enctype="multipart/form-data">
		{% csrf_token %}
		 {{form}}
		<button type="submit" class="saveBtn btn btn-primary col-sm-12">Save</button >
	</form>
</div>
{% endblock %}
	

수동으로 랜더링도 가능하다.

	<form
		{% /csrf_token %}
 		<div class="form-group">
	    {{form.title.label_tag}}
	    <input type="text" class="form-control" id="{{ form.title.id_for_label }}" aria-describedby="title" placeholder="title">
	  	</div>
	  	<div class="form-group">
	    <label for="{{ form.content.id_for_label }}">내용:</label>
	    <input type="text" class="form-control" id="{{ form.content.id_for_label }}" aria-describedby="contents" placeholder="contents">
	  	</div>
		<button type="submit" class="saveBtn btn btn-primary col-sm-12">Save</button >
	</form>

urls.py 에 edit url을 추가 한다.

		url(r'^edit/(?P<\pk>\d+)/$', views.post_edit, name='post_edit'),

forms.py

django Docs: Form field

	
	from django import forms
	from .models import Post

	 class PostForm(forms.Form):
		title = forms.CharField(label='제목', max_length=100)
		content = forms.CharField(label='내용')
	

view.py

	
	from django.shortcuts import render, get_object_or_404, redirect
	from django.http import HttpResponse
	from .models import Post
	from .forms import PostForm ## 추가

	def post_edit(request, pk):
	post = get_object_or_404(Post, pk=pk)
	if request.method == "POST":
		form = PostForm(request.POST, request.FILES, instance=post) ##추가하고자 하는 글의 Post모델 인스턴스를 가져옴
		if form.is_valid():
			post = form.save(commit=False)
			post.author = request.user
			post.published_date = timezone.now()
			post.save()
		return redirect('post_detail', pk=post.pk)
	else:
		form = PostForm()

	return render(request, 'pages/post/post_edit.html', {'form': form, 'post':post})
	

image 위에서 보면 알 수 있듯이 정말 간단히 form 을 자동으로 랜더링 할 수 있다.


meta클래스를 이용해서 form을 만들 수도 있다. (개인적으로 이방법을 더 선호 한다.)

forms.py

	
from django import forms
from .models import Post
EMPTY_TITLE_ERROR = "제목을 입력하세요"
EMPTY_CONTENT_ERROR = "내용을 입력하세요"


	class Meta:
		model = Post
		fields = ('categoryCd','title','content','published_date')
		labels = {
			'categoryCd' : '카테고리',
			'title':'제목',
			'content':'내용',
			'published_date':'개시일'
		}
		widgets = {
	 		'title': forms.TextInput({'class':'form-control'}),
			'content': forms.Textarea({'width': '100%', 'class':'form-control'}),
			'published_date' :forms.DateInput({'class':'form-control', 'type':'date'})
		}
		error_messages = {
			'title': {'required': EMPTY_TITLE_ERROR},
			'content': {'required': EMPTY_CONTENT_ERROR}
		}
	

views.py

	
	def post_edit(request, pk):
	post = get_object_or_404(Post, pk=pk)
	if request.method == "POST":
		form = PostForm(request.POST, request.FILES, instance=post) ##추가하고자 하는 글의 Post모델 인스턴스를 가져옴
		if form.is_valid():
			post = form.save(commit=False)
			post.author = request.user
			post.save()
		return redirect('post_detail', pk=post.pk)
	else:
		form = PostForm(instance=post)

	return render(request, 'pages/post/post_edit.html', {'form': form, 'post':post , 'page_tit' : post.title+' (수정)' })

	

post_list.html

	
{% extends 'simple.html' %}
{% load staticfiles %}
{% block simpleContents %}
<link rel="stylesheet" href="{% static 'css/post.css' %}">
<p class="bar_title hidden">{{post.title}}(edit)</p>
<div class="post_box row" style="margin-top:50px;">
	<form method="POST" class="post-form"  enctype="multipart/form-data" style="width:100%;">
		{% csrf_token %}
		{% for field in form %}
		<div class="form-group">
			{{field.label_tag}}
			{{field}}  
			{% if field.help_text %}
			<p class="help">{{ field.help_text|safe }}</p>
			{% endif %}
		</div>
		{% endfor %}

		<button type="submit" class="saveBtn btn btn-primary col-sm-12">Save</button >
	</form>
</div>
{% endblock %}

	

image

같은 방법으로 post_new을 만든다.

주의할 점은 view.py에서 new는 post를 따로 불러오지 않고, form을 불러올때 post를 주지 않아도 됨. 그리고 오늘 날짜로 setting 해줌.

	
def post_new(request):
	if request.method == "POST":
		form = PostForm(request.POST)
		if form.is_valid():
			post = form.save(commit=False) ##넘겨진 데이터를 바로 저장하지 말라는 뜻
			post.author = request.user
			post.save()
			return redirect('post_detail', pk=post.pk)
	else:
		form = PostForm(initial={'published_date':timezone.now()}) ## 오늘 날짜로 개시일 설정
	return render(request, 'pages/post/post_edit.html', {'form': form, 'page_tit':'새로운 포스트'})
	

image