- 폼을 만들 때 데이터베이스 기반의 앱을 구축하는 경우 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
📌적용
- 내가 선택한 투표 주제에 대해서만 투표를 진행해야하는데 다른 투표 주제들이 뜨는 문제가 발생했다. 이 부분을 해결하기 위해
ModelChoiceField
와 widget
의 HiddenInput
설정을 이용했다.
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)
class PollUpdateForm(forms.ModelForm):
options = forms.CharField(label="투표 선택 옵션", max_length=300)
class Meta:
model = Topic
fields = ['title']
labels = {
'option' : '선택지',
'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을 이용한 인스턴스 생성 시에 인자로 지정하여 기존 데이터가 폼에 들어갈 수 있도록 하는 것이다.
참고 자료 - 초보몽키의 개발 블로그