Django Basic 1-6) ModelForm

Turtle·2023년 12월 20일
0
post-thumbnail

📌ModelForm

  • 폼을 만들 때 데이터베이스 기반의 앱을 구축하는 경우 Django 모델과 밀접하게 매핑되는 양식을 갖게 될 가능성이 있다.
  • 아래는 BlogComment 모델로 사람들이 댓글을 제출할 수 있는 양식을 만드는 모델이다. 이 경우 모델에서 필드를 이미 정의했기 때문에 폼을 새로 만들어 양식에서 필드 유형을 다시 정의한다면 중복이 발생한다.
  • 이런 이유로 Django는 Django 모델에서 Form 클래스를 생성할 수 있는 도우미 클래스를 제공한다.
from django.forms import ModelForm
from myapp.models import Article

class ArticleForm(ModelForm):
	class Meta:
    	model = Article
        fields = ['pub_date', 'headline', 'content', 'reporter']

📌Field types

  • 생성된 Form 클래스에는 fields 속성에 지정된 순서대로 지정된 모델 필드에 대한 양식 필드가 있다.
  • 각 모델 필드에는 기본 양식 필드와 일치하는 필드가 있다. Django 공식 문서에 관련 자료가 있으니 추후 참고하는 용도로 링크를 걸어놓겠다.

참고 자료 - Django Field types


📌적용

  • 내가 선택한 투표 주제에 대해서만 투표를 진행해야하는데 다른 투표 주제들이 뜨는 문제가 발생했다. 이 부분을 해결하기 위해 ModelChoiceFieldwidgetHiddenInput 설정을 이용했다.
class VoteForm(forms.ModelForm):
    topic = forms.ModelChoiceField(queryset=Topic.objects.all(), widget=forms.HiddenInput)
    class Meta:
        model = Vote
        fields = ['topic', 'option']
def vote_poll(request, id):
    topic = Topic.objects.get(id=id)
    if request.method == "POST":
        form = VoteForm(request.POST)
        if form.is_valid():
            form.save()
            return HttpResponseRedirect('/votes/polls/%d' % id)
    else:
        form = VoteForm()
    
   	# 폼의 초기값을 선택한 투표 주제로 지정
    form.fields['topic'].initial = topic	
	# 선택한 투표 주제에 해당하는 옵션을 쿼리셋을 이용하여 가져오기
    form.fields['option'].queryset = Option.objects.filter(topic=topic).all()
    
    context = {
        'form' : form,
        'topic' : topic,
    }
    return render(request, 'votes/vote_poll.html', context)

📌ModelForm을 활용한 Model Instance 수정

class PollUpdateForm(forms.ModelForm):
    options = forms.CharField(label="투표 선택 옵션", max_length=300)
    class Meta:
        model = Topic
        fields = ['title']
        labels = {
            'option' : '선택지',	# 한글로 쉽게 변환 가능(by labels)
            'title' : '제목',
        }
def update_poll(request, id):
    topic = Topic.objects.get(id=id)

    if request.method == "POST":
        form = PollUpdateForm(request.POST, instance=topic)
        if form.is_valid():
            form.save()

            # 기존 옵션을 먼저 삭제
            Option.objects.filter(topic=topic).delete()

            # 새로운 옵션을 추가
            new_options = form.cleaned_data['options'].split(",")
            for item in new_options:
                Option.objects.create(name=item, topic=topic)
            return HttpResponseRedirect('/votes/polls/%d' % id)
    else:
        form = PollUpdateForm(instance=topic)

    # 기존 옵션들에 추가할 수 있도록
    options = Option.objects.filter(topic=topic).all()
    joined = ",".join(item.name for item in options)
    form.fields['options'].initial = joined

    context = {
        'update_form' : form,
        'topic' : topic,
    }
    return render(request, 'votes/update_poll.html', context)
  • 수정 대상이 되는 Model Instance를 ModelForm 인스턴스 생성 시에 instance 인자로 지정한다.
  • 위의 코드를 보면 Topic 모델의 수정할 주제에 대한 ID값을 취해 해당 주제를 topic에 저장한 다음 ModelForm을 이용한 인스턴스 생성 시에 인자로 지정하여 기존 데이터가 폼에 들어갈 수 있도록 하는 것이다.

참고 자료 - 초보몽키의 개발 블로그

0개의 댓글