Сохраните связанные объекты перед тем, как редактировать реальный объект в администраторе django.

Можно ли сохранить связанные объекты до того, как реальный объект будет отредактирован в форме администратора 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 ответа

Решение

Следующее спасет детей в первую очередь:

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

У меня были проблемы с ответами в этом посте, поэтому я нашел более краткий ответ. У меня возникла проблема, потому что при использовании django-fsm другие ответы здесь будут пытаться сохранить модель несколько раз (один раз для каждого набора форм), а не один раз в конце.

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)

Это важно просто переворачивать порядок save_model и save_related, как это вызывается в источнике Django ModelAdmin

Ответ 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

В зависимости от того, что именно вы хотите сделать в своих сигналах, можете ли вы просто изменить post_save на pre_save для модели Child?

Другие вопросы по тегам