장고 폼 (form)

|

AskDjango 수업을 듣고 중요한 내용을 정리하였습니다.


form

  • 장고의 가장 큰 Feature 중 하나
  • Model 클래스와 유사하게 Form 클래스를 정의

주요역할 (custom form class)

  • 입력폼 html 생성 : as_table(), as_p(), as_ul() 기본 제공
  • 입력폼 값 검증 (validation)
  • 검증에 통과한 값을 사전타입으로 제공 (cleaned_data)

Form vs Model Form (폼과 모델폼의 차이점)

  • Form (일반 폼) : 직접 필드 정의, 위젯 설정이 필요
  • Model Form (모델 폼) : 모델과 필드를 지정하면 모델폼이 자동으로 폼 필드를 생성
from django import forms from .models import Post # Form (일반 폼) class PostForm(forms.Form): title = forms.CharField() content = forms.CharField(widget=forms.Textarea) # Model Form (모델 폼) class PostForm(forms.ModelForm): class Meta: model = Post fields = ['title', 'content'] 

Form Fields

  • 공식문서
  • Model Fields 와 유사
    • Model Fields : DB Field 듣을 파이썬 클래스화
    • Form Fields : HTML Form Field 들을 파이썬 클래스화

단계별 구현

django style

폼 처리 시에 같은 URL (같은 view) 에서 GET/POST로 나눠서 처리

def post_new(request): if request.method == 'POST': pass else: pass 
  • GET 방식 request
    • 입력폼을 보여준다
  • POST 방식 request
    • 데이터를 입력 받아서 검증 (validation)
    • 검증 성공 시 : 해당 데이터를 저장하고 success URL로 이동
    • 검증 실패 시 : 오류 메시지와 함께 입력폼을 다시 보여준다

Step 0. Model class 정의

# myapp/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): # redirect시 활용 return reverse('myapp:post_detail', args=[self.id]) 

Step 1. Form class 정의

# myapp/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 

Step 2. form 필드 별로 유효성 검사 함수 추가 적용

  • 기본 유효성 검사는 값의 유무
  • form 에서는 리턴값을 따로 처리하지 않고, forms.ValidationError 예외발생 유무로 처리
  • validators 는 form 보다 Model 에 적용하는게 좋다.
# myapp/forms.py from django import forms def min_length_3_validator(value): if len(value) < 3: raise forms.ValidationError('3글자 이상 입력해주세요') class PostForm(forms.Form): title = forms.CharField(validators=[min_length_3_validator]) # 한줄 문자입력창, 커스텀 validators 옵션 지정 가능 

참고 (models.py)

  • model class 정의시에 validators 옵션 적용 가능
  • 아래와 같이 model에 validators 를 정의하는 것을 권장 (Model Form에 그대로 적용 가능)
  • admin 사이트에서도 validator 동작 (admin도 Model Form을 생성하여 사용하기 때문)
from django import forms from django.db import models def min_length_3_validator(value): if len(value) < 3: raise forms.ValidationError('3글자 이상 입력해주세요') class Post(models.Model): title = models.CharField(max_length=100, validators=[min_length_3_validator]) 

Step 3. view 함수 내에서 form 인스턴스 생성

# myapp/views.py from django.shortcuts import render from .forms import PostForm def post_new(request): if request.method == 'POST': form = PostForm(request.POST, request.FILES) # NOTE: 인자 순서주의 POST, FILES else: form = PostForm() return render(request, 'dojo/post_form.html',{ 'form': form, }) 

Step 4. POST 요청에 한해 입력값 유효성 검증 및 저장처리

def post_new(request): if request.method == 'POST': form = PostForm(request.POST, request.FILES) # NOTE: 인자 순서주의 POST, FILES if form.is_valid(): # form의 모든 validators 호출 유효성 검증 수행 # 검증에 성공한 값들은 사전타입으로 제공 (form.cleaned_data) # 검증에 실패시 form.error 에 오류 정보를 저장 '''	# 저장방법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'])	post.save()	# 저장방법3)	post = Post.objects.create(title = form.cleaned_data['title'],	content = form.cleaned_data['content'])	# 저장방법4)	post = Post.objects.create(**form.cleaned_data) # unpack 을 통해 방법3과 같이 저장	''' # 저장방법5) post = form.save() # PostForm 클래스에 정의된 save() 메소드 호출 return redirect(post) # Model 클래스에 정의된 get_absolute_url() 메소드 호출 else: form = PostForm() return render(request, 'dojo/post_form.html',{ 'form': form, # 검증에 실패시 form.error 에 오류 정보를 저장하여 함께 렌더링 }) 

Step 5. 템플릿을 통해 HTML 폼 생성

  • GET 요청, POST 요청이지만 유효성 검증에 실패시, form 인스턴스를 통해 html 폼 출력
  • 오류메시지가 있다면 함께 출력
 <form action="" method="post">	{% csrf_token %} <table>	{{ form.as_table }} </table> <input type="submit"> </form>