본문 바로가기

Pyhon/Django

[Pyhon/Django] 장고 기초#015. 장고 폼 저장(Submit)하기

장고 폼

이전 문서에서는 장고 폼(ModelForm)을 사용하여 아래와 같은 html 문서를 작성하였습니다. 이번 문서에서는 실제 비즈니스 로직을 추가하여 폼을 저장 해보겠습니다.

장고 폼 저장(Submit)하기

blog/views.py 파일을 열어 아래 코드를 확인합니다. 이전 문서에서 작성한 post_new 뷰는 (+)링크를 클릭했을 때 호출되지만, 폼을 제출(post_edit.html의 button type="submit")할 때도 호출됩니다.

from django.shortcuts import render, get_object_or_404
from django.utils import timezone

from .models import Post
from .forms import PostForm

def post_list(request):
    posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date')
    return render(request, 'blog/post_list.html', { 'posts': posts })

def post_detail(request, pk):
    post = get_object_or_404(Post, pk=pk)
    return render(request, 'blog/post_detail.html', { 'post': post })

def post_new(request):
    form = PostForm()
    return render(request, 'blog/post_edit.html', { 'form': form })

폼을 제출하면서 뷰가 호출되면, 파라미터 request.POST에는 폼에서 입력한 데이터를 포함합니다. post_edit.html에서 form 태그의 method 어트리뷰트가 "POST"로 지정되어 있기 때문입니다.

폼 제출에 대한 비즈니스 로직을 구현하기 위해서 post_new 뷰를 아래와 같이 수정합니다. post_new 뷰는 두 가지 경우(폼을 호출할 때, 제출 할 때) 실행되기 때문에 이에 대한 분기 처리를 추가합니다.

def post_new(request):
    if "POST" == request.method:
        form = PostForm(request.POST)
    else:
        form = PostForm()
    return render(request, 'blog/post_edit.html', { 'form': form })

폼을 제출하기 위해서 뷰가 호출되었을 때는 request.method는 "POST" 입니다. 이 때 request.POST에는 폼(forms.py의 PostForm)을 포함하며, 웹 브라우저(post_edit.html)에서 사용자가 입력한 정보들이 저장되어 있습니다. 폼을 호출하는 경우는 이전과 동일한 비즈니스 로직(빈 폼-PostForm을 템플릿에 전달)을 갖습니다.

다음으로 사용자가 폼에 입력한 데이터가 유효한지 검사하는 단계를 거칩니다. form.is_valid() 함수가 그 역할을 수행하는데, 검증 로직에 대해서는 따로 알려줄 필요가 없습니다. 장고 ORM에 의해서 이미 Post 모델에 대한 스키마를 프로그램이 알고 있기 때문입니다.

def post_new(request):
    if "POST" == request.method:
        form = PostForm(request.POST)
        if form.is_valid():
            post = form.save(commit=False)
            post.author = request.user
            post.published_date = timezone.now()
            post.save()
    else:
        form = PostForm()
    return render(request, 'blog/post_edit.html', { 'form': form })

form.save()는 폼에 연결되어 있는 모델을 반환합니다. 이 정보 역시 forms.py에서 이미 작성한 내용입니다. PostForm 폼은 Post 모델을 지정하고 있습니다.

class PostForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = ('title', 'text', )

form.save() 인자로 입력된 commit=False는 모델을 리턴하기 전에 데이터베이스에 저장(commit) 할 것인지에 대한 옵션입니다. author, published_date와 같은 html 폼 입력에 없었던 다른 필드를 비즈니스 로직에서 핸들링하기 위해서 이 단계에서는 커밋하지 않습니다. author, published_date를 모두 입력하고 나서야 모델을 수동으로 save()하는 것으로 커밋합니다.

끝으로 폼 제출이 완료되면 웹 브라우저에서 새로 작성한 포스트로 이동할 수 있도록 합니다. 이를 위해서 redirect 모듈을 import 해야 합니다.

from django.shortcuts import render, get_object_or_404, redirect

...

def post_new(request):
    if "POST" == request.method:
        form = PostForm(request.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, 'blog/post_edit.html', { 'form': form })

post.save()가 수행되어 데이터베이스에 Post 모델 데이터가 커밋되고 나면, 웹 브라우저 페이지를 post_detail 뷰를 통해 리디렉션 할 수 있도록 합니다. 이 때 pk는 방금 작성한 Post 모델에 대한 pk입니다. 리디렉션 된 뷰가 호출되면 방금 커밋한 포스트의 세부 정보를 읽어(get_object_or_404)와서 post_detail.html 템플릿에 전달하고, 웹 브라우저는 템플릿에 의해 렌더링 된 post_detail.html으로 이동하게 됩니다.

이제 웹 브라우저(http://127.0.0.1:8000/)에서 포스트 작성을 진행합니다. 이전 문서에서는 폼의 내용을 입력하고 submit 하여도 아무 응답이 없었으나, 이번 문서를 잘 진행하였다면 새로운 포스트 작성이 성공적으로 진행되는 것을 확인 할 수 있습니다.