[我在Django users 上发布了这个 | 谷歌组也是。]
使用inline formset docs中的示例,我可以编辑属于特定模型的对象(使用 modelforms)。我一直在尝试遵循相同的模式来 使用内联表单集创建新对象,但一直无法清醒到足以为此目的带来工作视图。
使用与上述链接相同的示例,我将如何创建“作者”模型的新实例及其相关的“书”对象?
[我在Django users 上发布了这个 | 谷歌组也是。]
使用inline formset docs中的示例,我可以编辑属于特定模型的对象(使用 modelforms)。我一直在尝试遵循相同的模式来 使用内联表单集创建新对象,但一直无法清醒到足以为此目的带来工作视图。
使用与上述链接相同的示例,我将如何创建“作者”模型的新实例及其相关的“书”对象?
首先,创建一个作者模型表单。
author_form = AuthorModelForm()
然后创建一个虚拟作者对象:
author = Author()
然后使用虚拟作者创建一个内联表单集,如下所示:
formset = BookFormSet(instance=author) #since author is empty, this formset will just be empty forms
将其发送到模板。数据返回视图后,创建作者:
author = AuthorModelForm(request.POST)
created_author = author.save() # in practice make sure it's valid first
现在将内联表单集与新创建的作者挂钩,然后保存:
formset = BookFormSet(request.POST, instance=created_author)
formset.save() #again, make sure it's valid first
编辑:
要在新表单上没有复选框,请使用模板:
{% for form in formset.forms %}
<table>
{% for field in form %}
<tr><th>{{field.label_tag}}</th><td>{{field}}{{field.errors}}</td></tr>
{% endfor %}
{% if form.pk %} {# empty forms do not have a pk #}
<tr><th>Delete?</th><td>{{field.DELETE}}</td></tr>
{% endif %}
</table>
{% endfor %}
我实际上想对 nbv4 的解决方案提出一个小的调整:
假设您没有在 if-else 语句之外创建空的 created_author ,因此需要将 formset 嵌套在 author_form.is_valid() 中以避免在 author_form 无效时出现运行时错误(因此没有实例化 created_author )。
代替:
if request.method == 'POST':
author_form = AuthorModelForm(request.POST)
if author_form.is_valid():
created_author = author_form.save()
formset = BookFormSet(request.POST, instance=created_author)
if formset.is_valid():
formset.save()
return HttpResponseRedirect(...)
else:
...
请执行下列操作:
if request.method == 'POST':
author_form = AuthorModelForm(request.POST)
if author_form.is_valid():
created_author = author_form.save(commit=False)
formset = BookFormSet(request.POST, instance=created_author)
if formset.is_valid():
created_author.save()
formset.save()
return HttpResponseRedirect(...)
else:
...
此版本避免在 book_formset 有机会验证之前提交 created_author。要纠正的用例是有人用无效的 BookFormSet 填写了有效的 AuthorForm 并不断重新提交,从而创建了多个没有 Books 关联的 Author 记录。这似乎适用于我的项目跟踪器应用程序(将“作者”替换为“项目”,将“书”替换为“角色”)。
models.py(联系方式)
class Contact(models.Model)
first = models.CharField(max_length=30)
middle = models.CharField('M.I.',max_length=30, blank=True)
last = models.CharField(max_length=30)
sort_order = models.PositiveIntegerField(default=99)
模型.py(链接)
class Link(models.Model):
contact = models.ForeignKey(Contact)
link = models.URLField()
description = models.CharField(max_length=30)
access_date = models.DateField(blank=True,null=True)
表格.py
from django.forms import ModelForm
from contacts.models import Contact
class ContactAjaxForm(ModelForm):
class Meta:
model=Contact
视图.py
def edit(request,object_id=False):
LinkFormSet = inlineformset_factory(Contact, Link, extra=1)
if object_id:
contact=Contact.objects.get(pk=object_id)
else:
contact=Contact()
if request.method == 'POST':
f=forms.ContactAjaxForm(request.POST, request.FILES, instance=contact)
fs = LinkFormSet(request.POST,instance=contact)
if fs.is_valid() and f.is_valid():
f.save()
fs.save()
return HttpResponse('success')
else:
f = forms.ContactAjaxForm(instance=contact)
fs = LinkFormSet(instance=contact)
return render_to_response(
'contacts/edit.html',
{'fs': fs, 'f': f, 'contact': contact}
)
这不是基于书中的示例,它是从我网站上的一些代码中编辑下来的。我还没有测试它,所以可能会有一些错误,但总的来说它应该是可靠的。不建议使用 Contact 的空实例,但它可以节省一些逻辑并且可以正常工作。
编辑: 添加了链接模型,切换到普通外键而不是通用外键,这令人困惑