使用内联表单创build模型和相关模型
[我已经发布在Django用户| Google网上论坛也是。]
使用内嵌表单文档中的示例,我可以编辑属于特定模型的对象(使用模型)。 我一直试图按照相同的模式来创build使用内联窗体的新对象,但一直没有足够清晰的头脑为此目的提出一个工作的看法。
使用与上述链接相同的示例,我将如何创build“作者”模型的新实例以及相关的“书籍”对象?
首先,创build一个作者模型表单。
author_form = AuthorModelForm()
然后创build一个虚拟的作者对象:
author = Author()
然后使用虚拟作者创build一个内联formset,如下所示:
formset = BookFormSet(instance=author) #since author is empty, this formset will just be empty forms
发送到一个模板。 数据返回到视图后,您创build作者:
author = AuthorModelForm(request.POST) created_author = author.save() # in practice make sure it's valid first
现在将内联表单与新创build的作者挂钩,然后保存:
formset = BookFormSet(request.POST, instance=created_author) formset.save() #again, make sure it's valid first
编辑:
要在新窗体上没有checkbox,这是一个模板:
{% 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的解决scheme:
假设您不会在if-else语句之外创build空的created_author,因此需要在author_form.is_valid()中嵌套formset以避免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: ...
这个版本避免了提交created_author,直到book_formset有机会validation。 用例要纠正的是有人用无效的BookFormSet填充了一个有效的AuthorForm,并不断重新提交,创build了多个没有与之关联的书籍的logging。 这似乎适用于我的项目跟踪器应用程序(用“angular色”replace“作者”与“项目”和“书”)。
models.py(联系人)
first = models.CharField(max_length=30) middle = models.CharField('MI',max_length=30, blank=True) last = models.CharField(max_length=30) sort_order = models.PositiveIntegerField(default=99)
models.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)
forms.py
from django.forms import ModelForm from contacts.models import Contact class ContactAjaxForm(ModelForm): class Meta: model=Contact
views.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})
这不是基于本书中的例子,它是从我的网站上的一些代码编辑。 我没有testing过,所以可能会有一些bug总体来说应该是坚实的。 使用一个空的Contact实例不是build议的方法,但它节省了一些逻辑,它的工作原理。
编辑:添加链接模型,切换到正常的外键,而不是通用的外键,这是混乱