关于 Django中的nested form fields

当前我有三个模型,如下列出的简化的模型定义

class Article(models.Model):
     title...
     content...

class Attachment(models.Model):
     file...
     article = models.ForeignKey(Article, ref_name = 'attachments')

class Photo(models.Model):
     image...
     article = models.ForeignKey(Article, ref_name = 'photos')
现在的需求是,我在新建一篇article时候,如果,这个article中有图片,或者附件,那么可以在一个form中一起post到服务器端,在新建article后将附属的附件或者照片一起保存下来。

在Rails中有一个非常方便的解决方案,就是在模型中定义accepts_nested_attributes_for ,接着就能在html中使用fields_for标签。

在Django中,使用的inline formset来实现的。
inline formset的创建使用的是通过 inlineformset_factory :
inlineformset_factory(parent_model,model,form=ModelForm,
    formset=BaseInlineFormSet,fk_name=None,
    fields=None,exclude=None,
    extra=3,can_order=False,can_delete=True,max_num=None,
    formfield_callback=None,widgets=None,validate_max=False)
在我这个例子中parent_model 对应的Article, model对应的是Attachment或者Photo
AttachmentInlineFormset = inlineformset_factory(Article, Attachment, extra = 1)
PhotoInlineFormset = inlineformset_factory(Article, Photo, extra = 1)

实例化inline formset:

attachment_formset = AttachmentInlineFormset(**self.get_form_kwargs(), prefix = 'attachments')
photo_formset = PhotoInlineFormset(**self.get_form_kwargs(), prefix = 'photos')

在CreateView或者UpdateView中,使用

class XXView(CreateView):   
     def form_valid(self, form):
         instance = form.save(commit = False)
         attachment_formset = AttachmentInlineFormset(instance = instance, prefix = 'attachments', **self.get_form_kwargs())
         photo_formset = PhotoInlineFormset(instance = instance, prefix = 'photos', **self.get_form_kwargs())
         if attachment_formset.is_valid() and photo_formset.is_valid():
             instance = form.save()
             for fs in [attachment_formset, photo_formset]:
                 fs.instance = instance
                 fs.save()
             return HttpResponseRedirect(self.get_success_url())
         else:
             return self.form_invalid(self, form)

你可能感兴趣的:(django,formset,inline_formset)