在 Django 中,可以通过使用 ModelForm
和 InlineFormSet
来实现多层(嵌套)模型表单。这样可以在一个表单中同时编辑主模型及其相关的子模型。下面是一个示例,演示如何实现这种多层嵌套的表单。
1、问题背景
- 如何使用 Django 的 Form 来创建涉及多个模型的多层嵌套表单?
- 在 Django 初学者使用 Form 时遇到了错误“invalid literal for int() with base 10: ‘test’”。
- 需要创建涉及多个模型的表单,例如“测验-问题-答案”模型,并且每个测验包含多个问题,每个问题有多个答案。
2、解决方案
- 方法一
- 使用 Django 的 ModelForm 来创建各个模型的表单。
- 手动将这些表单组合成一个多层表单。
- 需要考虑保存数据的顺序,即先保存最底层的模型,然后是中间层的模型,最后是顶层的模型。
- 方法二
- 使用 Django 的
InlineFormSet
和ModelForm
来创建多层表单。 InlineFormSet
可以用来创建嵌套的表单集,其中每个表单集对应一个模型。ModelForm
可以用来创建单个模型的表单。- 将这些表单集和表单组合在一起,就可以生成一个多层表单。
- 使用 Django 的
代码示例
方法一:手动组合表单
from django.forms import ModelForm, Formclass QuizForm(ModelForm):class Meta:model = Quizclass QuestionForm(ModelForm):class Meta:model = Questionclass AnswerForm(ModelForm):class Meta:model = Answerclass MultiLayerForm(Form):quiz_form = QuizForm()question_forms = QuestionFormSet(queryset=Question.objects.filter(quiz=None))answer_forms = AnswerFormSet(queryset=Answer.objects.filter(question=None))def view_function(request):if request.method == 'POST':quiz_form = QuizForm(request.POST)question_forms = QuestionFormSet(request.POST, queryset=Question.objects.filter(quiz=None))answer_forms = AnswerFormSet(request.POST, queryset=Answer.objects.filter(question=None))if quiz_form.is_valid() and all(form.is_valid() for form in question_forms) and all(form.is_valid() for form in answer_forms):# Save the formsquiz = quiz_form.save()for question_form in question_forms:question = question_form.save(commit=False)question.quiz = quizquestion.save()for answer_form in answer_forms:answer = answer_form.save(commit=False)answer.question = questionanswer.save()return HttpResponseRedirect('/')else:quiz_form = QuizForm()question_forms = QuestionFormSet(queryset=Question.objects.filter(quiz=None))answer_forms = AnswerFormSet(queryset=Answer.objects.filter(question=None))return render(request, 'form.html', {'quiz_form': quiz_form, 'question_forms': question_forms, 'answer_forms': answer_forms})
方法二:使用 InlineFormSet
和 ModelForm
from django.forms import ModelForm, inlineformset_factoryclass QuizForm(ModelForm):class Meta:model = QuizQuestionFormSet = inlineformset_factory(Quiz, Question, fields=('label',))
AnswerFormSet = inlineformset_factory(Question, Answer, fields=('label', 'correct'))def view_function(request):if request.method == 'POST':quiz_form = QuizForm(request.POST)question_forms = QuestionFormSet(request.POST, instance=quiz_form.instance)answer_forms = AnswerFormSet(request.POST, instance=question_forms.instance)if quiz_form.is_valid() and all(form.is_valid() for form in question_forms) and all(form.is_valid() for form in answer_forms):# Save the formsquiz = quiz_form.save()question_forms.save()answer_forms.save()return HttpResponseRedirect('/')else:quiz_form = QuizForm()question_forms = QuestionFormSet(instance=quiz_form.instance)answer_forms = AnswerFormSet(instance=question_forms.instance)return render(request, 'form.html', {'quiz_form': quiz_form, 'question_forms': question_forms, 'answer_forms': answer_forms})
通过上述步骤,你可以创建一个嵌套的表单界面,使得用户可以在同一页面上输入主模型及其相关子模型的信息。这种方法非常适合需要处理多层数据结构的应用场景。