【发布时间】:2020-06-12 02:18:38
【问题描述】:
假设我有以下 Django 模型,它们表示父子关系之间的排序关系:
class Parent(models.Model):
name = models.CharField(max_length=50)
children = models.ManyToManyField("Child", through="ParentChild")
class Child(models.Model):
name = models.CharField(max_length=50)
class ParentChild(models.Model):
class Meta:
constraints = [
models.UniqueConstraint(fields=["parent", "child"], name="uc_parent_child"),
models.UniqueConstraint(fields=["parent", "sort_number"], name="uc_parent_child"),
]
parent = models.ForeignKey(Parent, on_delete=models.CASCADE)
child = models.ForeignKey(Child, on_delete=models.CASCADE)
sort_number = models.IntegerField()
def save(self, *args, **kwargs):
exising_sort_numbers = self.parent.parentchild_set.values_list(
"sort_number", flat=True
)
if self.sort_number in exising_sort_numbers:
raise Exception(f"Duplicate sort number: {self.sort_number}")
super().save(*args, **kwargs)
现在,如果我使用直通模型创建关系,则会出现重复 sort_number 的异常:
ParentChild.objects.create(parent=parent, child=child1, sort_number=0)
ParentChild.objects.create(parent=parent, child=child2, sort_number=0) # raises Exception
但是,如果我使用 .add 方法创建关系,则不会出现异常:
parent.children.add(child1, through_defaults={"sort_number": 0})
parent.children.add(child2, through_defaults={"sort_number": 0}) # does NOT raise Exception
我知道using the .add method doesn't call the .save method on the through model,所以我需要使用m2m_change 信号来运行这个逻辑。但我不确定如何在这个信号中获得sort_number。到目前为止,这是我对信号的代码:
@receiver(m2m_changed, sender=Parent.children.through)
def validate_something(sender, instance, action, reverse, model, pk_set, **kwargs):
if action == "pre_add":
for pk in pk_set:
child = model.objects.get(pk=pk)
exising_sort_numbers = instance.parentchild_set.values_list(
"sort_number", flat=True
)
# where's sort_number specified in through_defaults ???
知道如何获取此值并执行"pre_add" 验证,还是这不可能?
【问题讨论】:
标签: django django-models django-signals