Save the related objects before the actual object being edited on django admin

浪尽此生 提交于 2019-11-28 08:31:31

The following will save the children first:

class ParentAdmin(admin.ModelAdmin):
    inlines = [ChildInline]

    def save_model(self, request, obj, form, change):
        pass # don't actually save the parent instance

    def save_formset(self, request, form, formset, change):
        formset.save() # this will save the children
        form.instance.save() # form.instance is the parent

I was having issues with the answers in this post, so I figured out a more concise answer. I was having an issue because using django-fsm, the other answers here would try to save the model multiple times (once for every formset) rather than once at the end.

def save_model(self, request, obj, form, change):
    if not obj.pk: # call super method if object has no primary key 
        super(YourAdmin, self).save_model(request, obj, form, change)
    else:
        pass # don't actually save the parent instance

def save_related(self, request, form, formsets, change):
    form.save_m2m()
    for formset in formsets:
        self.save_formset(request, form, formset, change=change)
    super(YourAdmin, self).save_model(request, form.instance, form, change)

This essential just flips the order of save_model and save_related as called in Django ModelAdmin source

ccrisan's answer brought me on the right track, but I think there is a flaw regarding save behavior of instances that do not yet exist in the database. In this case it's not possible to save the related objects first, because there is no foreign key that they can point to. For me the following extension did the trick:

class ParentAdmin(admin.ModelAdmin):
    inlines = [ChildInline]

    def save_model(self, request, obj, form, change):
        if not obj.pk: # call super method if object has no primary key 
            super(ParentAdmin, self).save_model(request, obj, form, change)
        else:
            pass # don't actually save the parent instance

    def save_formset(self, request, form, formset, change):
        formset.save() # this will save the children
        form.instance.save() # form.instance is the parent

Depending on what you exactly want to do in your signals, can you just change the post_save to pre_save for the Child model ?

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!