티스토리 뷰
Form
- 장고를 더욱 장고스럽게 만들어주는 주옥같은 Feature
- Model클래스와 유사하게 Form클래스를 정의
- 주요 역할 : 커스텀 Form클래스를 통해 ...
- 입력폼 HTML 생성 : .as_table(), .as_p(), .as_ul() 기본제공
- 입력폼 값 검증(validation) 및 값 변환
- 검증을 통과한 값들을 사전타입으로 제공 (cleaned_data)
def post_new(request): if request.method == 'POST': form = PostForm(request.POST, request.FILES) if form.is_valid(): post = Post(**self.cleaned_data) post.save() return redirect(post) else: form = PostForm() return render(request, 'blog/post_form.html', { 'form': form, }) |
Django Style
폼 처리 시에 같은 URL(즉 같은 뷰)에서 GET/POST로 나눠 처리
- GET방식으로 요청될 때 : 입력폼을 보여줍니다.
- POST방식으로 요청될 때
- 데이터를 입력받아 유효성 검증 과정을 거칩니다.
- 검증 성공 시 : 해당 데이터를 저장하고 SUCCESS URL로 이동
- 검증 실패 시 : 오류메세지와 함께 입력폼을 다시 보여줍니다.
Step 1) Form 클래스 정의
#dojo/models.py from django.db import models # Create your models here. class Post(models.Model): title = models.CharField(max_length=100) content = models.TextField() created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) |
# dojo/forms.py # 앱 내에서 forms.py파일을 만들어 준다 from django import forms class PostForm(forms.Form): title = forms.CharField() content = forms.CharField(widget=form.Textarea) # widget을 통해 여러줄 입력 받는줄로 변환한다. |
(설명) : 현재 models은 데이터베이스에대한 모델 필드이며, db를 제외한 코드내에 문자열은 모든 문자열이므로,
forms필드를 통해서 html위젯을 생성 할때 문자는 똑같은 문자열일뿐 길이 제한에 따라서 필드 타입을 구분 할 필요가 없다.
(중요) 값이 있는지만 검사 한다.
Step 2) 필드 별로 유효성 검사 함수 추가 적용
# dojo/validators.py from django import forms def min_length_3_validator(value): if len(value) < 3: raise forms.ValidationError('3글자 이상 입력해주세요.') # dojo/forms.py from django import forms class PostForm(forms.Form): title = forms.CharField(validators=[min_length_3_validator]) # 유저로 입력 받은 값이 min_length_3_validator value에 들어가서 유효성 검사 content = forms.CharField(widget=form.Textarea) |
Step 3) View함수 내에서 Form 인스턴스 생성
GET요청을 통해 View 함수가 호출이 될 때,
GET/POST 요청을 구분해서 Form 인스턴스 생성 1
# dojo/views.py from .forms import PostForm if request.method == 'POST': # POST 요청일 때 form = PostForm(request.POST, request.FILES) # 순서가 바뀌면 안되며, 항상 POST가 앞으로와야한다. 유저부터 입력받은 데이터를 넘긴다. else: # GET 요청일 때 form = PostForm() # 빈폼 return render(request, 'dojo/post_form.html',{'form' : form,}) |
Step 4) POST요청에 한해 입력값 유효성 검증
# dojo/views.py if request.method == 'POST': # POST인자는 request.POST와 request.FILES를 제공받음. form = PostForm(request.POST, request.FILES) # 파일업로드가 불필요한경우 생략 가능
# 인자로 받은 값에 대해서, 유효성 검증 수행 if form.is_valid(): # 검증이 성공하면, True 리턴 # 검증에 성공한 값들을 사전타입으로 제공받음. # 검증에 성공한 값을 제공받으면, Django Form의 역할은 여기까지 !!! # 필요에 따라, 이 값을 DB에 저장하기 # 방법1) ''' post = Post() post.title = form.cleaned_data['title'] post.content = form.cleaned_data['content'] post.save() ''' # 방법2) ''' post = Post(title=form.cleaned_data['title'], content=form.cleaned_data['content']) ''' # 방법3) ''' post = Post.objects.create(title=form.cleaned_data['title'], contnet=form.clenad_data['contet']) ''' # 방법4) post = Post.objects.create(**form.cleaned_data) return redirect('/success_url/') else: # 검증에 실패하면, form.errors와 form.각필드.errors 에 오류정보를 저장 form.errors else: form = PostForm() return render(request, 'myapp/form.html', {'form': form}) |
Step 5) 템플릿을 통해 HTML폼 생성
GET요청이거나 POST요청이지만 유효성 검증에서 실패했을 때 Form 인스턴스를 통해 HTML폼 출력 오류메세지도 있다면 같이 출력
## 검색을 제외하고 form
<table> <form action="" method="post"> {% csrf_token %} <table>{{ form.as_table }}</table> <input type="submit" /> </form> </table> |
csrf 토큰발급을 통한, 값 자동 생성
<input type='hidden' name='csrfmiddlewaretoken' value='ZDtPkYrqPVwfVEbZ5zTcgO2OlvwijjYOawrlgsXz3HjdPcwSXvWDQBDEhPCPakQr' />
GET /dojo/new/ HTTP/1.1" 200 528 # 기본 Form 요청
POST /dojo/new/ HTTP/1.1" 200 547 # 제출버튼 누르면서 POST로 변경
{'title': 'hello', 'content': 'world'}
Step 6)
유저가 입력폼에 내용을 채우고 전송(submit)을 하면 해당 URL로 POST요청으로 전달하여 다시 유효성 검증 수행
전체 소스
# dojo/models.py from django.db import models from django.urls import reverse class Post(models.Model): title = models.CharField(max_length=100) content = models.TextField() created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) def get_absolute_url(self): return reverse('blog:post_detail', args=[self.id]) # dojo/forms.py from django import forms class PostForm(forms.Form): title = forms.CharField() content = forms.CharField(widget=form.Textarea) # ModelForm.save 인터페이스를 흉내내어 구현 def save(self, commit=True): post = Post(**self.cleaned_data) if commit: post.save() return post # dojo/views.py from django.shortcuts import render from .forms import PostForm from .models import Post def post_new(request): if request.method == 'POST': form = PostForm(request.POST, request.FILES) if form.is_valid(): post = form.save() return redirect(post) else: form = PostForm() return render(request, 'dojo/post_form.html', {'form': form,}) <!-- dojo/templates/dojo/post_form.html --> <table> <form action="" method="post"> {% csrf_token %} <table>{{ form.as_table }}</table> <input type="submit" /> </form> </table> |
Form Fields
- Model Fields 와 유사
- Model Fields : Database Field 들을 파이썬 클래스화
- Form Fields : HTML Form Field 들을 파이썬 클래스화
- BooleanField, CharField, ChoiceField, DateField,DateTimeField, EmailField, FileField, ImageField, FloatField,IntegerField, RegexField 등
"""본 내용은 AskDjango VOD, "장고 차근차근 시작하기" 강의내용을 참고하여 작성했습니다.(https://nomade.kr/)"""
'Python > * Django' 카테고리의 다른 글
20. Form Template Custom Render (0) | 2017.12.27 |
---|---|
19. ModelForm (0) | 2017.12.20 |
17. HttpRequest and HttpResponse (0) | 2017.12.18 |
16. CSRF(Cross-Site Request Forgery) (0) | 2017.12.15 |
15. HTML Form (0) | 2017.12.15 |