- 在 Django 中,希望在一个模板中展示两个表单,并且使用两个不同的模型。尝试了多种方法,但都未成功。最初有 2 个视图、2 个模型和 2 个表单。在搜索后发现人们使用 inlineformsets,因此删除了一个视图并设置了 inlineformset。
当前卡在以下问题上:
- 模板呈现到浏览器后,“object_list”部分按照预期显示数据库内容,“form”部分呈现表单并正确验证/保存数据。
- “formset”部分存在问题。未呈现任何字段(由于字段是外键,因此期望看到下拉列表),并且在按“提交”按钮后会收到错误消息:“AttributeError at /settings/ 'NoneType' object has no attribute 'save'”。
- 解决方案
以下是解决此问题的步骤:
- 导入必要的模块:
from django import forms
from django.forms.models import inlineformset_factory
from .models import RevisionSettings, RevisionDefaultType
- 定义表单类:
class SettingsForm(forms.ModelForm):
class Meta:
model = RevisionSettings
class DefaultSettingsForm(forms.ModelForm):
class Meta:
model = RevisionDefaultType
- 定义表单集:
SettingsFormSet = inlineformset_factory(RevisionSettings, RevisionDefaultType)
- 在视图中,在
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))
- 在视图中,在
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)
- 在模板中,使用
{% 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 %}
这样,就可以在一个模板中展示两个表单,并且使用两个不同的模型。