一个模板中展示两个表单

83 阅读1分钟
  1. 在 Django 中,希望在一个模板中展示两个表单,并且使用两个不同的模型。尝试了多种方法,但都未成功。最初有 2 个视图、2 个模型和 2 个表单。在搜索后发现人们使用 inlineformsets,因此删除了一个视图并设置了 inlineformset。

当前卡在以下问题上:

  • 模板呈现到浏览器后,“object_list”部分按照预期显示数据库内容,“form”部分呈现表单并正确验证/保存数据。
  • “formset”部分存在问题。未呈现任何字段(由于字段是外键,因此期望看到下拉列表),并且在按“提交”按钮后会收到错误消息:“AttributeError at /settings/ 'NoneType' object has no attribute 'save'”。
  1. 解决方案

以下是解决此问题的步骤:

  1. 导入必要的模块:
from django import forms
from django.forms.models import inlineformset_factory
from .models import RevisionSettings, RevisionDefaultType
  1. 定义表单类:
class SettingsForm(forms.ModelForm):

    class Meta:
        model = RevisionSettings

class DefaultSettingsForm(forms.ModelForm):

    class Meta:
        model = RevisionDefaultType
  1. 定义表单集:
SettingsFormSet = inlineformset_factory(RevisionSettings, RevisionDefaultType)
  1. 在视图中,在 get 方法中实例化表单和表单集:
def get(self, request, *args, **kwargs):
    self.object = None
    form_class = self.get_form_class()
    form = self.get_form(form_class)
    formset = SettingsFormSet(instance = RevisionSettings)
    return self.render_to_response(
        self.get_context_data(form=form,
                              formset=formset))
  1. 在视图中,在 post 方法中处理表单和表单集的提交:
def post(self, request, *args, **kwargs):
    self.object = None
    form_class = self.get_form_class()
    form = self.get_form(form_class)
    formset = SettingsFormSet(self.request.POST)
    if 'rev_settings_form_1' in self.request.POST:
        if form.is_valid():
            return self.form_valid(form)
        else:
            return self.form_invalid(form)
    elif 'rev_settings_form_2' in self.request.POST:
        if formset.is_valid():
            return self.formset_valid(formset)
        else:
            return self.form_invalid(formset)
  1. 在模板中,使用 {% for %} 遍历对象列表,并使用 {{ formset.management_form }}{% for form in formset %} 来渲染表单集:
{% extends 'base_private.html' %}

{% block content %}

    {% for object in object_list %}

        <tr>
            <td align="center">{{ object.global_revision_type }}</td>
            <td align="center">{{ object.global_revision_description }}</td>
            <td align="center"><a href="/settings/{{ object.id }}/delete" class="tooltip-test" title="" data-original-title="Delete selected revision type"><span class="glyphicon glyphicon-remove-circle"></span></a></td>
        </tr>

    {% endfor %}

    <form action = '{{ action }}' method = 'POST' class="form-horizontal" role="form">
        {% csrf_token %}

        <tr>
            <td align="center">
                {{ formset.management_form }}
                {% for form in formset %}
                    {{ form.id }}
                    {{ form.defaultrevisiontype.label_tag }}
                    {{ form.defaultrevisiontype }}
                {% endfor %}
            </td>
        </tr>

        <span class="input-group-addon">
                <input type = 'submit' name = 'rev_settings_form_2' value = 'Update Default Revision Type' class = 'btn btn-success'>
        </span>

            <td align="center">{{ form.global_revision_type }}{{ form.global_revision_type.errors }}</td>
            <td align="center">{{ form.global_revision_description }}{{ form.global_revision_description.errors }}</td>
        </tr>

        <span class="input-group-addon">
                <input type = 'submit' name = 'rev_settings_form_1' value = 'Add Revision Type' class = 'btn btn-success'>
        </span>

    </form>

{% endblock %}

这样,就可以在一个模板中展示两个表单,并且使用两个不同的模型。