Django ModelForm이란?

2022. 1. 19. 12:34강의 정리/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)를 배우기 시작한 입문자이시거나, 또는 배우고 싶은 생각이 있으신 분은 위 출처의 강의를 적극 추천드립니다!!!

 

 


ModelForm

  • 장고 Form을 상속
  • 지정된 Model로부터 필드정보를 읽어들여, Form Field를 세팅
  • 내부적으로 Model 객체를 유지
  • 유효성 검증에 통과한 값들로, 지정 Model 객체로의 저장을 지원함

 

 

#instagram/forms.py

from django import forms
from .models import Post


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

 

 

 

 

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

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

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

 

 

 


ModelForm.save(commit=True)

  • Form의 cleaned_data(is_valid()를 통해서 유효한 데이터들이 저장된 변수)를 Model 객체(instance) 생성에 사용하고, 그 객체를 리턴
  • commit=True #디폴트 값
    • model 객체의 save() 및 form.save_m2m()#many to many을 호출
    • form.save() != instance.save()
  • commit=False
    • instance.save() 함수 호출을 지연시키고자할 때 사용

 

 

따라서 form.save()를 사용 시 자동적으로 DB에 내용이 저장되고 반영됩니다.
여기서 DB 저장 여부를 commit=True, False와 같은 flag를 통해 지정해줄 수 있습니다.
commit=False는 DB에 반영하지 않는 것을 의미합니다.

 

 

 

#instagram/views.py

def post_new(request):
    
    """
    중략
    """
            post = form.save()
    """
    중략
    """
    return render(request, 'instagram/post_form.html',{
        'form' : form,
    })

 

 

ModelForm.save(commit=False) 예시

  • 새 포스팅시 작성자를 고르지않고 싶을 때

 

https://whatisthenext.tistory.com/131

 

[Django] 폼(Form)에서 commit=False의 의미

<!DOCTYPE html> form Commit=False Django에서 모델 Form을 다루다보면 종종 commit=False 라는 코드를 마주칠 때가 있다. 가끔씩 헷갈리는 부분이기 때문에 장고 공식문서를 통해 학습하고자 한다. save(commit=..

whatisthenext.tistory.com

 

#instagram/views.py

@login_required
def post_new(request):
    if request.method == 'POST':
        form = PostForm(request.POST, request.FILES)
        if form.is_valid():
            post = form.save(commit=False)
            post.author = request.user # 현재 로그인한 유저 Instance
            post.save()
            # post의 detail.html로 이동함.
            return redirect(post)
    else:         
        form = PostForm()
        
    return render(request, 'instagram/post_form.html',{
        'form' : form,
    })
  • 위 코드 프로세스
    1. is_valid()를 통해서 유효성 검사를 통과하였다면
    2. model instance(=post)의 author를 현재 로그인한(request한) User로 설정한다.
    3. 그후 model instance(=post)를 저장한다.
  • 이 때 중요한 것은 위 과정은 필히 로그인이 되어있다는 인증을 받은 후 진행되어야 하기에 장식자로 @login_required를 적어줌

 

@login_required
def post_new(request):
     		"""
            중략
            """
        if form.is_valid():
            comment = form.save(commit=False)
            comment.ip = request.META['REMOTE_ADDR'] # IP를 기록하고 save()
            """
            중략
            """
    return render(request, 'instagram/post_form.html',{
        'form' : form,
    })
  • 참고로 IP주소는 model 필드에
    models.GenericIPAddressField 가 존재한다.
     
     

 

#instagram/forms.py

class PostForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = [
            'message', 'photo', 'tag_set', 'is_public'
        ]

 

 

  • 작성자만 글을 수정하게 만들려면???
    if post.author != request.user:
        messages.error(request, '작성자만 수정 가능합니다!')
        return redirect(post)

 

 

 

 

 


View에서의 ModelForm 처리 (New, 새로운 것 생성)

#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()
            # post의 detail.html로 이동함.
            return redirect(post)
    else:         
        form = PostForm()
        
    return render(request, 'instagram/post_form.html',{
        'form' : form,
    })

 

 

 

View에서의 ModelForm 처리 (Edit,  수정하기)

#instagram/views.py

def post_edit(request, pk):
    post = get_object_or_404(Post, pk=pk)

    if request.method == 'POST':
        form = PostForm(request.POST, request.FILES, instance=post)
        if form.is_valid():
            post = form.save()
            # post의 detail.html로 이동함.
            return redirect(post)
    else:         
        form = PostForm(instance=post)
        
    return render(request, 'instagram/post_form.html',{
        'form' : form,
    })
  • get_object_or_404() 함수는 Django 모델을 첫번째 인자로 받고, 몇개의 키워드 인수를 모델 관리자의 get() 함수에 넘깁니다. 만약 객체가 존재하지 않을 경우, Http404 예외가 발생합니다.

 

 

 

폼 인스턴스 데이터에 접근시 cleaned_data를 통해서 접근해야한다.

올바른 예시

form = CommentForm(request.POST)
	
    messages = form.cleaned_data['message']

 

틀린 예시

form = CommentForm(request.POST)
	
    messages = request.POST['messages']

 

 

 


도움 받은 문서

 

반응형