【问题标题】:Save the related objects before the actual object being edited on django admin在 django admin 上编辑实际对象之前保存相关对象
【发布时间】:2013-01-29 07:04:19
【问题描述】:

是否可以在 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

【问题讨论】:

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


    【解决方案1】:

    下面会先救孩子们:

    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】:

      我对这篇文章中的答案有疑问,所以我想出了一个更简洁的答案。我遇到了一个问题,因为使用 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)
      

      这个本质只是颠倒了Django ModelAdmin source中调用的save_model和save_related的顺序

      【讨论】:

      • 不确定这是 Django 版本的东西,还是业务逻辑的东西,但对于 Django 1.11 和我的用法。这似乎是正确的答案
      【解决方案3】:

      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
      

      【讨论】:

        【解决方案4】:

        根据您确切想要在信号中执行的操作,您可以将子模型的 post_save 更改为 pre_save 吗?

        【讨论】:

          猜你喜欢
          • 2012-04-26
          • 1970-01-01
          • 2020-08-24
          • 1970-01-01
          • 2021-09-20
          • 2023-03-03
          • 1970-01-01
          • 2017-04-12
          • 2011-09-19
          相关资源
          最近更新 更多