当前位置: 首页 > article >正文

Django Form 实现多层(嵌套)模型表单

在 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})

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


http://www.kler.cn/a/380826.html

相关文章:

  • 修炼内功之函数栈帧的创建与销毁
  • golang , chan学习
  • 【微信小程序】2|轮播图 | 我的咖啡店-综合实训
  • docker 部署win系统
  • 【已解决】黑马点评项目Redis版本替换过程中误删数据库后前端显示出现的问题
  • javaEE--计算机是如何工作的-1
  • 深度学习模块创作(缝合)教程|适合1-360月小宝宝食用,干货满满
  • 深度学习基础知识-损失函数
  • 【C/C++】memcpy函数的模拟实现
  • Mac OS 配置Docker+Mysql
  • C++中的继承——第一篇
  • ​CSS之三
  • 【OJ题解】C++实现字符串大数相乘:无BigInteger库的字符串乘积解决方案
  • vue中强制更新视图
  • 网络信息系统的整个生命周期
  • 服务器作业2
  • AUTOSAR COM 模块的主要功能导读以及示例
  • 【jvm】如何设置Eden、幸存者者区的比例
  • C语言 | Leetcode C语言题解之第521题最长特殊序列I
  • C++模拟实现list
  • NRF52832学习笔记(41)——添加串口库libuarte
  • GPT-SoVITS 部署方案
  • sqlalchemy连接mysql数据库
  • 全面解析:大数据技术及其应用
  • 鸿蒙开启无线调试
  • dockerdockerfiledocker-compose操作nginx