我认为最好用一个例子来解释。
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 Admin区域中,我单击父记录(P1)并将其外键设置为GrandParent记录(GP1)。
我希望这可以级联到所有Child记录。换句话说,每个已经有P1外键的子记录都应该自动获得GP1的外键。
是否有Django方法可以做到这一点?
谢谢。
答案 0 :(得分:1)
一旦您需要真正的业务逻辑,我个人就不会使用管理页面,但这里的答案是:
如果您只需要从管理页面执行此操作,则只需覆盖管理员保存功能
即可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()
希望这有帮助。