Django:表单中的多个表单集

时间:2015-03-26 18:25:03

标签: django formset

我正在研究一些Django表单,其代码库是从其他人继承的,这很好,但却增加了混乱。

我正在尝试将第二个formset添加到表单中。添加第二个formset时,两个formset都出现在页面上,但似乎在后端不包含任何表单。以下是我的代码示例(我添加的内容可能比推荐更多,但我不想错过重要内容):

view.py:

class Thing(StaffRequiredMixin, DetailView):
model = models.Thing

def post(self, request, *args, **kwargs):

    ...

    context = self.get_context_data(**kwargs)

    dispatch = {
        "thing_form": self.handle_thing_form,
        ...
    }

    return dispatch[self.request.POST.get("form_name")](context)

...

def get_context_data(self, *args, **kwargs):

    context = super(Thing, self).get_context_data(*args, **kwargs)
    thing = self.model.objects.get(pk=self.kwargs["pk"])
    context["thing"] = thing

    to_handle = self.request.POST.get("form_name")

    if to_handle == "thing_form":
        context["thing_form"] = forms.Thing(
                   self.request.POST, 
                   instance=thing)

        context["formset1"] = forms.FormSet1(
                   self.request.POST,
                   queryset=models.Model1.objects.filter(thing=self.object),
                   prefix="thing1")

        context["formset2"] = forms.FormSet2(
                   self.request.POST, 
                   queryset=models.Model2.objects.filter(thing=self.object),
                   prefix="thing2")
    else:
        context["thing_form"] = forms.Thing(
                   instance=thing, 
                   user=self.request.user)

        context["formset1"] = forms.FormSet1(
                   queryset=models.Model1.objects.filter(thing=self.object),
                   prefix="stuff1")

        context["formset2"] = forms.FormSet2(
                   queryset=models.Model2.objects.filter(thing=self.object),
                   prefix="stuff2")

    # Other to_handle stuff
    ...

    return context

def handle_thing_form(self, context):

    form = context['thing_form']
    formset1 = context['formset1']
    formset2 = context['formset2']

    if form.is_valid() and formset1.is_valid() and formset2.is_valid():

        # Do some form logic
        ...

        form.save()

        # Formset stuff:
        # here, the formsets contain no forms
        changed_1 = [f for f in formset1 if f.has_changed()]
        changed_2 = [f for f in formset2 if f.has_changed()]

        for a_form in changed_1:

            #Do some formset logic
            ...

            a_form.save()

        for a_form in changed_2:
            #similar to 1

        return HttpResponseRedirect(self.get_next_url())

    return self.render_to_response(context)

forms.py:

class Form1(ModelForm):

    class Meta:
        model = models.Model1
        fields = ("field1", "field2", ...)

    def __init__(self, *args, **kwargs):

        super(Form1, self).__init__(*args, **kwargs)

        # Some readonly widget stuff etc
        ...


class Form2(ModelForm):

    #Same idea as Form1
    ...


FormSet1 = modelformset_factory(models.Model1, form=Form1, extra=0)
FormSet2 = modelformset_factory(models.Model2, form=Form2, extra=0)

模板:

<form id="thing-form" method="post">
    <input type="hidden" name="form_name" value="thing_form" />

    {% for field in thing_form.visible_fields %}

        {{ field }}
        ...

    {% endfor %}


    <a id="add-form1">Add</a>

    {{formset1.management_form}}
    <div id="formset1-div">

        {% for form in formset1.forms %}

            {{form.id}}
            {% for field in form.visible_fields %}

                <div class="controls">
                    {{field}}
                </div>

            {% endfor %}
        {% endfor %}
    </div>

    <div id="empty-form1>

        {% for field in formset1.empty_form.visible_fields %}
            <div class="controls">
                {{field}}
            </div>
        {% endfor %}
    </div>

    {{formset2.management_form}}
    <div id="formset2-div">

        {# same idea as above #}
        ...

    </div>

    <button type="submit">Update</button>
</form>

的javascript:

$(document).ready(function(){

    $('#add-form1').click(function() {
        $('#formset1-div').prepend($('#empty_form1').html().replace(/__prefix__/g, 'thing1'));
        $('#id_form-TOTAL_FORMS').val(parseInt('thing1') + 1);
    });

    if ($("#formset1-div input").length === 0){
        $("#add-form1").trigger("click");
    }

    // Similar button stuff for formset2
    ...

})

无论如何,我在这里添加了很多,但我这样做是因为我不确定我哪里出错了,或者即使我想做的事情也是可能的。

1 个答案:

答案 0 :(得分:1)

哇,我真傻。 javascript部分应该是这样的:

$(document).ready(function(){

    $('#add-form1').click(function() {
        var thing1_index = $('#id_thing1-TOTAL_FORMS').val();
        $('#formset1-div').prepend($('#empty_form1').html().replace(/__prefix__/g, thing1_index));
        $('#id_thing1-TOTAL_FORMS').val(parseInt(thing1_index) + 1);
    });

    if ($("#formset1-div input").length === 0){
        $("#add-form1").trigger("click");
    }

    // Similar button stuff for formset2
    ...

})

不确定我是如何错过显而易见的parseInt('thing1')毫无意义的。

无论如何,它现在有效。也许有人在查看多个表单集时会发现这里的内容很有用¯\_(ツ)_/¯