django泛型CreateView和UpdateView中的Modelformset

时间:2015-04-19 06:23:00

标签: python django modelform formset

我有一个模型组织,其中包含两个字段'id'和'name'。我打算用动态模型formsets填充它。我到目前为止的代码如下。

形式

class OrganizationForm(forms.ModelForm):
    class Meta:
        model = Organization
        fields = ('name',)

OrganizationFormset = modelformset_factory(Organization, form=OrganizationForm, fields=('name', ), extra=1)

视图

class OrganizationCreate(CreateView):
    model = Organization
    form_class = OrganizationForm

    def get_context_data(self, **kwargs):
        context = super(OrganizationCreate, self).get_context_data(**kwargs)
        context['formset'] = OrganizationFormset()
        return context

    def post(self, request, *args, **kwargs):
        formset = OrganizationFormset(request.POST)
        if formset.is_valid():
            return self.form_valid(formset)

    def form_valid(self, formset):
        formset.save()
        return HttpResponseRedirect('/')

    def form_invalid(self, formset):
        return self.render_to_response(self.get_context_data(formset=formset))


class OrganizationUpdate(UpdateView):
    model = Organization
    form_class = OrganizationForm
    template_name_suffix = '_update_form'

    def get_context_data(self, **kwargs):
        context = super(OrganizationUpdate, self).get_context_data(**kwargs)
        context['formset'] = OrganizationFormset()
        return context

    def post(self, request, *args, **kwargs):
        formset = OrganizationFormset(request.POST)
        if formset.is_valid():
            return self.form_valid(formset)

    def form_valid(self, formset):
        formset.save()
        return HttpResponseRedirect('/')

    def form_invalid(self, formset):
        return self.render_to_response(self.get_context_data(formset=formset))

模板 创建

<form id="myForm" method="post" action="">
            {% csrf_token %}
            {% for hidden in form.hidden_fields %} {{ hidden }} {% endfor %}
           {{ form }}
           <table border="0" cellpadding="0" cellspacing="0">
               <tbody>
                   {% for form in formset.forms %}
                   {% for hidden in form.hidden_fields %} {{ hidden }} {% endfor %}
                   <tr>
                      <td>
                         {% if form.instance.pk %}{{ form.DELETE }}{% endif %}

                         {{ form.field1 }}
                      </td>
                      <td>{{ form.name }}</td>
                   </tr>
                   {% endfor %}
               </tbody>
           </table>
           {{ formset.management_form }}
            <input type="submit" value="Create Location">
       </form>

更新

<form id="myForm" method="post" action="">
            {% csrf_token %}

           <table border="0" cellpadding="0" cellspacing="0">
               <tbody>
                   {% for form in formset.forms %}
                   {% for hidden in form.hidden_fields %} {{ hidden }} {% endfor %}
                   <tr>
                      <td>
                         {% if form.instance.pk %}{{ form.DELETE }}{% endif %}

                         {{ form.field1 }}
                      </td>
                      <td>{{ form.name }}</td>
                   </tr>
                   {% endfor %}
               </tbody>
           </table>
           {{ formset.management_form }}
            <input type="submit" value="Update organizations">
       </form>

但是,创建模板和更新模板都会显示预先存在的组织,而这只应在更新模板中进行。此外,在更新页面中删除预先存在的组织会返回以下错误:

The view aims.views.OrganizationUpdate didn't return an HttpResponse object. It returned None instead.

我是django通用视图和使用formset的新手。我做错了什么?

提前致谢。

2 个答案:

答案 0 :(得分:6)

默认情况下,django model formsets会显示可以从数据库中找到的任何项目。因此,在创建一个参数时,您必须覆盖queryset参数,以便让它知道要使用哪些项目以及何时使用。例如,您应该提供 -

Organization.objects.none()

这样的创建视图 -

class OrganizationCreate(CreateView):
    ...

    def get_context_data(self, **kwargs):
        ...
        context['formset'] = OrganizationFormset(queryset=Organization.objects.none()) # providing none

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

    def form_valid(self, formset):
        ...

    def form_invalid(self, formset):
        ...

这将强制formset呈现一个空白表单。同样更改更新视图以编辑特定项目 -

class OrganizationUpdate(UpdateView):
    ...

    def get_context_data(self, **kwargs):
        context = super(OrganizationUpdate, self).get_context_data(**kwargs)
        context['formset'] = OrganizationFormset(queryset=Organization.objects.get(pk=< get the pk from url when editing>))
        return context

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

    def form_valid(self, formset):
        ...

    def form_invalid(self, formset):
        ...

希望这可以解决您的问题。如果您仍然看到问题,请更新问题以及网址和可能的屏幕截图。我会看到我能做些什么。

答案 1 :(得分:0)

当基于类的视图(创建和更新)中的formset无效时,post方法不返回任何内容,您应该在form_invalid分支中返回else

if formset.is_valid():
    return self.form_valid(formset)
else:
    return self.form_invalid(formset)