티스토리 뷰

Python/* Django

18. Form

포꾼 2017. 12. 19. 15:32

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
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함