问题
Is it possible to save the related objects before the actual object being edited on a django admin form?
For example:
in models.py
class Parent(model.Model):
pass
class Child(model.Model):
parent = models.ForeignKey(Parent)
@receiver(post_save,sender = Parent)
def notify_parent_save(sender, instance=None, **kwargs):
print "Parent save"
@receiver(post_save,sender = Child)
def notify_child_save(sender, instance=None, **kwargs):
print "Child saved"
in admin.py
class ChildInline(admin.TabularInline):
model = Child
extra = 1
class ParentsAdmin(admin.ModelAdmin):
inlines = [ChildInline]
admin.site.register(Parent,ParentsAdmin)
Now, in django admin if I save a parent object, it will output on the console.
Parent save
Child save
I need this to happen in revese order:
Child save
Parent save
回答1:
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
回答2:
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
回答3:
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
回答4:
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 ?
来源:https://stackoverflow.com/questions/14858559/save-the-related-objects-before-the-actual-object-being-edited-on-django-admin