Skip to main content
 首页 » 编程设计

python之Django嵌套表单集动态添加表单

2024年08月16日29shangdawei

我正在尝试使用 Django 创建一个调查页面,该页面具有动态添加问题和选项(针对每个问题)的功能。我有以下三个模型类:调查、问题和选​​择。

我做了很多研究来弄清楚如何着手实现表单,使用 inline_formsets 的嵌套表单集似乎是正确的方法(I used this tutorial)。但是,我无法弄清楚如何使用嵌套表单集动态添加问题和选择。我尝试使用的 JavaScript 库(This library)没有嵌套表单集的示例,我不确定它是否支持它。 这段代码是我目前所拥有的:

表单.py

from django.forms import BaseInlineFormSet 
from django.forms import HiddenInput 
from django.forms import inlineformset_factory 
from django.forms import ModelForm 
 
from .models import * 
 
 
class SurveyForm(ModelForm): 
    class Meta: 
        model = Survey 
        fields = [ 
            'name', 
            'description', 
        ] 
 
 
class BaseQuestionFormset(BaseInlineFormSet): 
 
    def add_fields(self, form, index): 
        super(BaseQuestionFormset, self).add_fields(form, index) 
        form.nested = QuestionChoiceFormset( 
            instance=form.instance, 
            data=form.data if form.is_bound else None, 
            files=form.files if form.is_bound else None) 
 
    def is_valid(self): 
        result = super(BaseQuestionFormset, self).is_valid() 
        print(result) 
        if self.is_bound: 
            for form in self.forms: 
                if hasattr(form, 'nested'): 
                    result = result and form.nested.is_valid() 
 
        return result 
 
    def save(self, commit=True): 
        for form in self.forms: 
            form.save(commit=commit) 
        result = super(BaseQuestionFormset, self).save(commit=commit) 
 
        for form in self.forms: 
            if hasattr(form, 'nested'): 
                if not self._should_delete_form(form): 
                    form.nested.save(commit=commit) 
 
        return result 
 
 
QuestionFormset = inlineformset_factory( 
    parent_model=Survey, model=Question, fields='__all__', 
    formset=BaseQuestionFormset, extra=1) 
QuestionChoiceFormset = inlineformset_factory( 
    parent_model=Question, model=Choice, 
    fields='__all__', extra=1) 

View .py

@login_required 
def create(request): 
    survey = Survey() 
    if request.method == 'POST': 
        survey_form = SurveyForm(request.POST, instance=survey) 
        question_formset = QuestionFormset( 
            request.POST, prefix='questions', instance=survey) 
 
        if survey_form.is_valid() and question_formset.is_valid(): 
            survey_form.save() 
            question_formset.save() 
            # url = '/preview/{}'.format(survey.pk) 
            # return HttpResponseRedirect(url) 
    else: 
        survey_form = SurveyForm(instance=survey) 
        question_formset = QuestionFormset(instance=survey, prefix='questions') 
 
    context = { 
        'survey_form': survey_form, 
        'question_formset': question_formset, 
    } 
 
    return render(request, 'surveys/create.html', context) 

创建.html

{% extends 'surveys/base.html' %} 
{% load static %} 
{% block container %} 
<div class="container"> 
  <h1> Create New Survey </h1> 
  <form method="post"> 
    {% csrf_token %} 
    {{ question_formset.management_form }} 
    {{ question_formset.non_form_errors }} 
    {{ survey_form.as_p }} 
    <table id='myForm1'> 
      {% for question_form in question_formset.forms %} 
        {{ question_form }} 
 
        {% if question_form.nested %} 
          {{ question_form.nested.management_form }} 
          {{ question_form.nested.non_form_errors }} 
          <div id='myForm2'> 
          {% for choice_form in question_form.nested.forms %} 
            {{ choice_form }} 
          {% endfor %} 
          </div> 
        {% endif %} 
      {% endfor %} 
    </table> 
 
    <button type="save">Save</button> 
  </form> 
</div> 
<script src="{% static "surveys/dist/js/jquery.js" %}"></script> 
<script src="{% static "surveys/dist/js/jquery.formset.js" %}"></script> 
<script type="text/javascript"> 
  $(function(){ 
    $('#myForm1').formset({ 
      prefix: '{{ question_formset.prefix }}', 
      formCssClass: 'dynamic-question_formset', 
      addText: 'add question' 
    }); 
    $('#myForm2').formset({ 
      prefix: '{{ choice_form.prefix }}', 
      formCssClass: 'dynamic-choice_form', 
      addText: 'add choice' 
    }); 
  }) 
</script> 
{% endblock %}

请您参考如下方法:

我最终使用了 this plugin !它有嵌套表单集示例的解释。