在django admin上编辑实际对象之前保存相关对象

时间:2013-02-13 16:45:46

标签: django django-models django-admin django-signals

是否可以在django管理表单上编辑实际对象之前保存相关对象?

例如:

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"
admin.py

中的

class ChildInline(admin.TabularInline):
    model = Child
    extra = 1

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

admin.site.register(Parent,ParentsAdmin)

现在,在django admin中,如果我保存父对象,它将在控制台上输出。

Parent save
Child save

我需要按照改变顺序发生这种情况:

Child save
Parent save

4 个答案:

答案 0 :(得分:15)

以下内容将首先保存孩子:

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

答案 1 :(得分:7)

我在这篇文章中遇到了问题的答案,所以我想出了一个更简洁的答案。我遇到了一个问题,因为使用django-fsm,这里的其他答案会尝试多次保存模型(每个formset一次),而不是最后一次。

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)

这个必要的只是翻转了Django ModelAdmin source

中调用的save_model和save_related的顺序

答案 2 :(得分:4)

ccrisan的回答让我走上正轨,但我认为存在一个关于数据库中尚不存在的实例的保存行为的缺陷。在这种情况下,不可能首先保存相关对象,因为没有可以指向的外键。对我来说,以下扩展做了诀窍:

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

答案 3 :(得分:0)

根据您对信号的确切想要做什么,您是否可以将子模型的post_save更改为pre_save?