如何在一对多关系中级联更新?
How to cascade an update in a one-to-many relationship?
我认为最好用一个例子来解释。
class GrandParent(models.Model):
pass
class Parent(models.Model):
grandparent = models.ForeignKey(GrandParent, null=True, blank=True, default=None)
class Child(models.Model):
parent = models.ForeignKey(Parent, null=True, blank=True, default=None)
grandparent = models.ForeignKey(GrandParent, null=True, blank=True, default=None)
所以我们有三个 类。 Child 有 Parent 和 GrandParent 的外键,Parent 有 GrandParent 的外键。
在 Django 管理区域中,我单击父记录 (P1) 并将其外键设置为祖父记录 (GP1)。
我希望将其级联到所有子记录。换句话说,每个已经具有 P1 外键的子记录应该自动获得 GP1 的外键。
有没有 Django 方法可以做到这一点?
谢谢。
我个人不会在需要真正的业务逻辑时使用管理页面,但答案如下:
如果您只需要从管理页面执行此操作,您可以简单地覆盖管理保存功能
class ParentAdmin(admin.ModelAdmin):
list_display = ('id', 'parent', )
def save_model(self, request, obj, form, change):
obj.save()
for c in obj.child_set.all():
if c.granparent != obj.grandparent:
c.grandparent = obj.grandparent
c.save()
admin.site.register(Parent, ParentAdmin)
但是如果你想确保 Child 始终更新,无论是谁执行了 save(),你可以
1.- 覆盖模型的 save() 函数(但如果您的模型在不同的文件中,这可能会产生循环依赖:
class Parent(models.Model):
grandparent = models.ForeignKey(GrandParent, null=True, blank=True, default=None)
def save(self, *args, **kwargs):
for c in self.child_set.all():
if c.granparent != self.grandparent:
c.grandparent = self.grandparent
c.save()
super(Parent, self).save(*args, **kwargs)
2.- 为避免循环依赖,您可以使用信号捕获保存并对其进行操作
from django.db.models.signals import post_save
from django.dispatch import receiver
class Child(models.Model):
parent = models.ForeignKey(Parent, null=True, blank=True, default=None)
grandparent = models.ForeignKey(GrandParent, null=True, blank=True, default=None)
@receiver(post_save, sender=Parent)
def post_save_parent_callback(sender, **kwargs):
parent = kwargs['instance']
for c in parent.child_set.all():
if c.granparent != parent.grandparent:
c.grandparent = parent.grandparent
c.save()
希望这对您有所帮助。
我认为最好用一个例子来解释。
class GrandParent(models.Model):
pass
class Parent(models.Model):
grandparent = models.ForeignKey(GrandParent, null=True, blank=True, default=None)
class Child(models.Model):
parent = models.ForeignKey(Parent, null=True, blank=True, default=None)
grandparent = models.ForeignKey(GrandParent, null=True, blank=True, default=None)
所以我们有三个 类。 Child 有 Parent 和 GrandParent 的外键,Parent 有 GrandParent 的外键。
在 Django 管理区域中,我单击父记录 (P1) 并将其外键设置为祖父记录 (GP1)。
我希望将其级联到所有子记录。换句话说,每个已经具有 P1 外键的子记录应该自动获得 GP1 的外键。
有没有 Django 方法可以做到这一点?
谢谢。
我个人不会在需要真正的业务逻辑时使用管理页面,但答案如下:
如果您只需要从管理页面执行此操作,您可以简单地覆盖管理保存功能
class ParentAdmin(admin.ModelAdmin):
list_display = ('id', 'parent', )
def save_model(self, request, obj, form, change):
obj.save()
for c in obj.child_set.all():
if c.granparent != obj.grandparent:
c.grandparent = obj.grandparent
c.save()
admin.site.register(Parent, ParentAdmin)
但是如果你想确保 Child 始终更新,无论是谁执行了 save(),你可以
1.- 覆盖模型的 save() 函数(但如果您的模型在不同的文件中,这可能会产生循环依赖:
class Parent(models.Model):
grandparent = models.ForeignKey(GrandParent, null=True, blank=True, default=None)
def save(self, *args, **kwargs):
for c in self.child_set.all():
if c.granparent != self.grandparent:
c.grandparent = self.grandparent
c.save()
super(Parent, self).save(*args, **kwargs)
2.- 为避免循环依赖,您可以使用信号捕获保存并对其进行操作
from django.db.models.signals import post_save
from django.dispatch import receiver
class Child(models.Model):
parent = models.ForeignKey(Parent, null=True, blank=True, default=None)
grandparent = models.ForeignKey(GrandParent, null=True, blank=True, default=None)
@receiver(post_save, sender=Parent)
def post_save_parent_callback(sender, **kwargs):
parent = kwargs['instance']
for c in parent.child_set.all():
if c.granparent != parent.grandparent:
c.grandparent = parent.grandparent
c.save()
希望这对您有所帮助。