在 Django 中,可以通过使用 ModelFormInlineFormSet 来实现多层(嵌套)模型表单。这样可以在一个表单中同时编辑主模型及其相关的子模型。下面是一个示例,演示如何实现这种多层嵌套的表单。

在这里插入图片描述

1、问题背景

  • 如何使用 Django 的 Form 来创建涉及多个模型的多层嵌套表单?
  • 在 Django 初学者使用 Form 时遇到了错误“invalid literal for int() with base 10: ‘test’”。
  • 需要创建涉及多个模型的表单,例如“测验-问题-答案”模型,并且每个测验包含多个问题,每个问题有多个答案。

2、解决方案

  • 方法一
    • 使用 Django 的 ModelForm 来创建各个模型的表单。
    • 手动将这些表单组合成一个多层表单。
    • 需要考虑保存数据的顺序,即先保存最底层的模型,然后是中间层的模型,最后是顶层的模型。
  • 方法二
    • 使用 Django 的 InlineFormSetModelForm 来创建多层表单。
    • InlineFormSet 可以用来创建嵌套的表单集,其中每个表单集对应一个模型。
    • ModelForm 可以用来创建单个模型的表单。
    • 将这些表单集和表单组合在一起,就可以生成一个多层表单。

代码示例

方法一:手动组合表单

from django.forms import ModelForm, Form

class QuizForm(ModelForm):
    class Meta:
        model = Quiz

class QuestionForm(ModelForm):
    class Meta:
        model = Question

class AnswerForm(ModelForm):
    class Meta:
        model = Answer

class 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 forms
            quiz = quiz_form.save()
            for question_form in question_forms:
                question = question_form.save(commit=False)
                question.quiz = quiz
                question.save()
            for answer_form in answer_forms:
                answer = answer_form.save(commit=False)
                answer.question = question
                answer.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})

方法二:使用 InlineFormSetModelForm

from django.forms import ModelForm, inlineformset_factory

class QuizForm(ModelForm):
    class Meta:
        model = Quiz

QuestionFormSet = 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 forms
            quiz = 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})

通过上述步骤,你可以创建一个嵌套的表单界面,使得用户可以在同一页面上输入主模型及其相关子模型的信息。这种方法非常适合需要处理多层数据结构的应用场景。

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部