Python django具有相同模型和外键的多个ModelForms
我正在用Django构建一个简单的问答应用程序。我的简化模型是:Python django具有相同模型和外键的多个ModelForms,python,django,django-forms,Python,Django,Django Forms,我正在用Django构建一个简单的问答应用程序。我的简化模型是: class Question(models.Model): question_text = models.TextField('Question', max_length=256) class AnswerChoice(models.Model): choice_text = models.CharField('Choice', max_length=32) question = models.Forei
class Question(models.Model):
question_text = models.TextField('Question', max_length=256)
class AnswerChoice(models.Model):
choice_text = models.CharField('Choice', max_length=32)
question = models.ForeignKey(Question)
is_correct = models.BooleanField(default=False)
对于上述两个模型,我有两个ModelForm
s(QuestionForm
和AnswerChoiceForm
)
现在,我在HTML页面上显示了一个问题表单
和4个回答选项表单
s,用于编辑问题并为问题添加4个答案选项。我想确保用户只将一个答案标记为“正确”
我的查看功能是:
def edit_question(request):
if request.method == 'POST':
question_form = QuestionForm(request.POST)
choice_forms = [AnswerChoiceForm(request.POST, prefix=str(i))
for i in xrange(4)]
if all(c.is_valid() for c in choice_forms) and question_form.is_valid():
choices = [c.save(commit=False) for c in choice_forms]
question = question_form.save()
for c in choices:
c.question = question
c.save()
return HttpResponseRedirect(...) # show the question just added
# ...
现在,我想验证4个选项中有一个选项标记正确。我可以在上面的edit\u question
view函数中进行此检查,但不知何故,这似乎有点“错误”:我正在为一个视图函数添加核心逻辑,对此我并不完全满意
在我的问题
或回答选择
模型中,或在模型表单的定义中,是否有方法进行此验证
我没有在上面提供完整的最小代码,希望显示的代码数量足够,并且不会太长。如果您需要查看更多代码,请询问,我将编辑此帖子。一个选项如下:
class Question(models.Model):
question_text = models.TextField('Question', max_length=256)
def validate_answers(obj):
if obj.answerchoice_set.filter(is_correct=True).count()==1
#All well
return True
else:
#delete question and answers if you wish or request for change
return False
但你应该记住,这将检查你的答案是否有效后,一切都保存。如果你愿意,你可以删除你的问题或答案
def edit_question(request):
#your usual code
return (HttpResponseRedirect(...) if question.validate_answers() else HttpResponseRedirect(...))
这里的问题是,您没有为答案表单使用表单集。您应该:它们不仅没有单独实例化四个表单那么笨拙,而且它们还有一个
clean()
方法,专门用于验证子表单,而不是每个表单。大概是这样的:
class AnswerFormSet(forms.models.BaseInlineFormSet):
def clean(self):
correct_count = sum([form.cleaned_data['is_correct'] for form in self.forms])
if correct_count != 1:
raise forms.ValidationError('Exactly one answer must be marked as correct')
在视图中,您可以这样做:
def edit_question(request):
AnswerFormset = forms.models.inlineformset_factory(
Question, Answer, formset=AnswerFormSet, extra=4, max_num=4)
if request.method == 'POST':
question = Question()
question_form = QuestionForm(request.POST, instance=question)
answer_formset = AnswerFormset(request.POST, instance=question)
# Check these separately to avoid short-circuiting
question_valid = question_form.is_valid()
answer_valid = answer_formset.is_valid()
if question_valid and answer_valid:
question_form.save()
# No need to add new question as it was already set as the instance above
answer_formset.save()
# etc
非常感谢。这正是我需要的,而且更干净。我假设
返回self.cleaned_data
是AnswerFormSet
的clean()
方法中的一个输入错误?(Django抱怨没有这样的属性。)啊,是的,你不需要那一行,被删除了。这是可行的,但我想避免的一件事是在出现错误时将我的模型实例保存到数据库中。谢谢你的回答!