Django嵌套的formsets动态添加表单

时间:2018-03-16 22:37:05

标签: python jquery django-forms nested-forms inline-formset

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

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

forms.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)

views.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)

create.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 %}
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:2)

我最终使用this plugin!它有嵌套表单集的示例说明。