Django를 더 Django스럽게 만들어주는 Form

2022. 1. 18. 14:53강의 정리/Django Form

반응형

출처 : https://www.inflearn.com/course/%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EC%9E%A5%EA%B3%A0-%EC%9B%B9%EC%84%9C%EB%B9%84%EC%8A%A4/dashboard

 

장고(Django)를 배우기 시작한 입문자이시거나, 또는 배우고 싶은 생각이 있으신 분은 위 출처의 강의를 적극 추천드립니다!!!

 

 


 

Form

  • 장고를 더욱 장고스럽게 만들어주는 주옥같은 특징
  • 장고에서 가장 큰 비중을 차지하고있는 것은 model이고, model과 함께 장고 Form은 매우 중요한 기능이며, Form이나 Serialize를 사용하지 않는다면 굳이 장고를 쓸 필요가 없음.
  • 주요 역할
    • 입력폼 HTML 생성
    • 입력폼 값에 대한 유효성 검증 및 값 변환
    • 유효성 검증을 통과한 값들을 dict 형태로 제공
      #myapp/forms.py
      
      class PostForm(forms.Form):
      	title = forms.CharField()
          content = forms.CharField(widget=from.Textarea)
    • Form과 model의 차이점
      • model은 데이터베이스와의 상호작용을 담당
      • Form은 HTML Form과의 상호작용을 담당
    • widget 기능
      • HTML을 만들어주는 기능
  •  

 

 

 

 


 

Django Style의 Form 처리

  • 하나의 URL (하나의 View)에서 2가지 역할을 모두 수행
    1. 빈 폼을 보여주는 역할
    2. 폼을 통해 입력된 값을 검증하고 저장하는 역할
  • GET 방식으로 요청(request)받았을 때 즉 주소를 요청받았을 때
    • New/Edit 입력폼을 보여준다.
  • POST 방식으로 요청(request)받았을 때 즉 유저가 입력한 값을 전달 받았을 때
    • 데이터를 폼을 통해서 입력받아서 (request.POST, request.FILES) 유효성 검증 수행
    • 검증 성공 시 : 해당 데이터를 저장하고, SUCCESS URL로 이동함 #JSON 값 전달
    • 검증 실패 시 : 오류 메세지와 함께 입력폼을 다시 보여줌 #에러메세지를 JSON으로 전달

 

  • 장고에서 Form을 처리하는 일반적인 코드
def post_new(request):
    # POST 요청이라면 즉 유저가 입력한 값을 전달 받았다면
    if request.method == 'POST':
        form = PostForm(request.POST, request.FILES) # 첫번째 인자가 데이터, 두번째 인자가 FILES
        	
            # 유효성 검사에 성공하면 True 리턴
            if form.is_valid():
            	# 검증에 성공한 값들을 사전타입으로 제공받음
                # 검증에 성공한 값을 제공받으면, Django Form의 역할은 여기까지
                # 필요에 따라, 이값을 DB에 저장하기
               
                post = Post(**form.cleaned_data) # DB에 저장하기
                post.save()
                # 저장하고 임의의 주소로 이동
                return redirect(post)
  			  else: # 검증에 실패하면, form.errors와 form.각필드.errors에 오류 정보 저장
              		form.errors
    # GET 요청이라면 즉 주소 값을 전달 받았다면
    else:
    	# 빈 Form 객체 전달
        form = PostForm()

    return render(request, 'blog/post_form.html',{
        'form':form,
    })

 

 


Model Form

  • Form인데, 어떤 model로부터 어떤 Field를 가져오겠다 정의하면 Form이 model로부터 스스로 Field 정보를 가져와서 Form Field를 구성해준다. 즉 model이 변경된다면 자동으로 Model Form또한 변경된다. 
  • 매우 편리함!
#myapp/forms.py

class PostForm(forms.ModelForm):
	class Meta: # Meta 속성의
    	model = Post # 해당 모델로부터
        field = '__all__' # 가져올 필드 정보

 

 


필드 별로 유효성 검사 함수 추가 적용

  • 장고에서는 모델단에 유효성 검사 로직을 넣을 수 있다.
  • Form의 경우
# 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):
	# 원하는 유효성 검사 로직을 validators에 수행할 함수를 지정할 수 있다.
    # 함수는 필히 인자 하나만 받을 수 있고, Model단에도 넣을 수 있다.
	title = forms.CharField(validators=[min_length_3_validators])
    content = forms.CharField(widget=form.Textarea)

 

 

  • ModelForm의 경우
# myapp/forms.py
from django import forms

def min_length_3_validator(value):
	if len(value) < 3:
    		raise forms.ValidationError('3글자 이상 입력해주세요.')
        
class Post(forms.Model):
	# 원하는 유효성 검사 로직을 validators에 수행할 함수를 지정할 수 있다.
    # 함수는 필히 인자 하나만 받을 수 있고, Model단에도 넣을 수 있다.
	title = models.CharField(max_lenth=100, validators=[min_length_3_validators])
    content = models.TextField()

 

 

원래 Form을 그냥 만들 때에는 validators를 직접 필드에 지정했어야 했다. 즉 Model에도 지정을 해주어야하고, Form에도 지정을 해줘야하는데 그러면 로직이 분산되므로 관리하기가 매우 힘들다.

이 때
Model Form을 사용하면 Model단에 validators를 구현하게 되면, 자동으로 Form에도  validators 가져와진다. 

우리는 Model Form을 사용함으로서 Model단에서만 validators를 지정하면 된다!!!

 


실제 Form 구현해보기 #1

#instagram/models.py

from django.core.validators import MinLengthValidator

# validators 객체는 함수를 반환하여준다.
# 만약 3글자 미만의 문자열을 입력받으면 forms.ValidationError를 반환한다.
min_length_Validators = MinLengthValidator(3)



class Post(models.Model):
    message = models.TextField(
        validators=[min_length_Validators]
    )

 

 

#instagram/forms.py

from django import forms
from .models import Post


class PostForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = '__all__'

 

 

 


실제 Form 구현해보기 #2

#instagram/post_list.html

    <a href="{% url 'instagram:post_new' %}" class="btn btn-primary btn-block mt-4 mb-4">새 포스팅</a>

 

 

#instagram/post_form.html

<form action="" method="post" enctype="multipart/form-data">
    {% csrf_token %}
    <table>
        {{ form }}
    </table>
    <input type="submit" value="저장" />
</form>
  • GET 요청일 때
    • 유저가 Form을 채우고 submit하면 POST 요청
    • POST 요청이지만 유효성 검증에서 실패했다면
      • Form 인스턴스를 통해 HTML 폼 출력
      • 오류메세지도 있다면 같이 출력
      • 다시 유저가 Form을 채우고 submit하면 POST 재요청
  • method : 전송 방식
    • "GET" : 주로 데이터 조회 요청시에 사용
    • "POST" : 파괴적인 액션(생성/수정/삭제)에서 사용

 

#instagram/urls.py

urlpatterns = [ 
    path('new/', views.post_new, name='post_new'),
    ]

 

 

#instagram/models.py

from django.core.validators import MinLengthValidator

# validators 객체는 함수를 반환하여준다.
# 만약 3글자 미만의 문자열을 입력받으면 forms.ValidationError를 반환한다.
min_length_Validators = MinLengthValidator(3)




# Create your models here.

class Post(models.Model):
    message = models.TextField(
        validators=[min_length_Validators]
    )
  • 유효성 검사 로직은 되도록 model에서 처리하는게 장고의 철칙!

 

 

#instagram/forms.py

from django import forms
from .models import Post


class PostForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = '__all__'

 

 

#instagram/views.py

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, 'instagram/post_form.html',{
        'form' : form,
    })
  • view 함수 내에서 method에 따라 Form 객체 생성
    • if 조건체크를 POST에 대해 먼저 체크하는 것은 장고 스타일이다.
    • # GET 요청이 Form 객체 생성 이외에 특별한 역할이 없어서인듯 하다.

 

 


도움 받은 문서

 

 

반응형

'강의 정리 > Django Form' 카테고리의 다른 글

Django Form Validation  (0) 2022.01.19
Django ModelForm이란?  (0) 2022.01.19
Django Cross Site Request Forgery이란???  (0) 2022.01.18
HttpRequest, HttpResponse, JsonResponse  (0) 2022.01.17
Django HTML Form  (0) 2022.01.17