jc.jang

5강 ModelForm 본문

Django/Django - Form,ModelForm

5강 ModelForm

jangstory 2019. 9. 24. 20:57

주제

  • Model 내역대로 Form을 쓰고자 할 때에는 ModelForm을 사용하는 것이 Form을 사용하는 것 보다 간결하다.

  • Form을 사용하지만 거의 모든 코드는 Model 코드를 활용하기 때문에, 주요 코드는 Model을 통해 관리할 수 있다.

노트

  • ModelForm이란?

    • 장고 Form을 상속 받음

    • 지정된 Model로 부터 필드 정보를 읽어들여, Form Fields를 세팅함

    • 내부적으로 Model Instance를 유지

    • 유효성 검증에 통과한 값들로, 지정 Model Instance로의 저장 지원

  • ModelForm을 이용한 게시글 생성하기

  • myapp/models.py

from django.db import models
from django.core.validators import MinLengthValidator
from django.shortcuts import reverse


class Post(models.Model):
    title = models.CharField(max_length=100, validators=[MinLengthValidator(3)])
    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("post_detail", args=[self.pk])

    def __str__(self):
        return self.title
  • 게시글 모델 생성

 

  • myapp/forms.py

from django import forms

from .models import Post


class PostForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = '__all__'
  • 게시글 모델 폼 생성

 

  • myapp/urls.py

from django.urls import path

from . import views


urlpatterns = [
    path('', views.post_list, name='post_list'),
    path('new/', views.post_new, name='post_new'),
    path('<int:pk>/edit/', views.post_edit, name='post_edit'),
    path('<int:pk>/detail/', views.post_detail, name='post_detail'),
]
  • url을 등록한다.

 

  • myapp/views.py

def post_new(request):
    form_cls = PostForm
    template_name = 'myapp/post_form.html'
    success_url = '/'

    if request.method == 'POST':
        form = form_cls(request.POST, request.FILES)
        if form.is_valid():
            post = form.save()
            return redirect(post)
    else:
        form = form_cls()

    return render(request, template_name, {
        'form': form,
    })
  • 입력 폼을 PostForm으로 지정한다.

  • get 요청 시 입력 폼을 렌더링한다.

  • post 요청 시 입력 폼을 통해 들어온 데이터의 유효성을 확인하고 post 객체를 생성, 저장한다.

 

  • 게시글 수정하기

  • myapp/views.py

from django.shortcuts import render, redirect, get_object_or_404
from .forms import PostForm
from .models import Post


def post_edit(request, pk):
    form_cls = PostForm
    template_name = 'myapp/post_form.html'
    success_url = '/'

    post = get_object_or_404(Post, pk=pk)

    if request.method == 'POST':
        form = form_cls(request.POST, request.FILES, instance=post)
        if form.is_valid():
            post = form.save()
            return redirect(success_url)
    else:
        form = form_cls(instance=post)

    return render(request, template_name, {
        'form': form,
    })
  • form에 instance 항목을 설정하여 기존 데이터를 불러 올 수 있다.

 

  • ModelForm.save(commit=False) 사용하기

  • 댓글을 저장할 때 댓글 단 사용자의 IP도 저장하고 싶을 때는 어떻게 해야할까?

  • IP는 사용자로부터 입력 받는 것이 아니라, request의 'REMOTE_ADDR'로 확인할 수 있다.

  • 댓글 내용을 입력 받고 IP를 지정해주고 댓글을 저장하면 된다.

 

  • myapp/models.py

from django.db import models

class Comment(models.Model):
    post = models.ForeignKey(Post, on_delete=models.CASCADE)
    author = models.CharField(max_length=20)
    message = models.TextField()
    ip = models.CharField(max_length=15)

    def __str__(self):
        return "{}: {}".format(self.author, self.message)
  • 댓글 모델을 생성한다.

 

  • myapp/forms.py

from django import forms

from .models import Comment


class CommentForm(forms.ModelForm):
    class Meta:
        model = Comment
        fields = ['author', 'message']
  • 댓글 모델 폼을 생성한다. PostForm과 다른 점은 모든 필드를 사용자로부터 받지 않는다는 점이다.

  • 댓글에 연결된 Post와 IP 필드는 받지 않고 view에서 처리한다.

 

  • myapp/urls.py

from django.urls import path

from . import views


urlpatterns = [
	...
    path('<int:post_pk>/comment/new', views.comment_new, name='comment_new'),
    path('<int:post_pk>/comment/<int:pk>/edit', views.comment_edit, name='comment_edit'),
]
  • url을 등록한다.

  • 댓글을 생성하기 위해 어느 글에 연결할 건지(Foreignkey)알아야하기 때문에 post_pk를 통해 파악한다.

 

  • myapp/views.py

from django.shortcuts import render, redirect, get_object_or_404
from .forms import CommentForm
from .models import Comment


def comment_new(request, post_pk):
    form_cls = CommentForm
    template_name = 'myapp/comment_form.html'
    success_url = '/'

    post = get_object_or_404(Post, pk=post_pk)

    if request.method == 'POST':
        form = form_cls(request.POST, request.FILES)
        if form.is_valid():
            comment = form.save(commit=False)
            comment.post = post
            comment.ip = request.META['REMOTE_ADDR']
            comment.save()
            return redirect(success_url)
    else:
        form = form_cls()

    return render(request, template_name, {
        'form': form,
    })
  • url에서 인자로 넘겨받은 post_pk를 통해 post 모델을 조회한다.

  • 유효성 검사 후 form.save(commit=False)를 통해 객체를 생성하고 저장은 하지 않는다.

  • 댓글의 post와 ip를 설정하고 comment.save()를 통해 댓글을 저장한다.

요약

  • modelform을 사용하면 form을 간략하게 쓸 수 있고 model에서 제약을 추가하면 된다.

  • form.save(commit=False)를 통해 객체를 생성하고 다른 필드의 값을 지정 혹은 변환하고 저장할 수 있다.

 

 

 

'Django > Django - Form,ModelForm' 카테고리의 다른 글

7장 Widget Overview  (0) 2019.09.25
6강 Form Validation  (0) 2019.09.25
4강 CSRF  (0) 2019.09.24
3강 Form  (0) 2019.09.24
2강 HttpRequest와 HttpResponse  (0) 2019.09.17
Comments