【发布时间】:2019-11-27 07:51:24
【问题描述】:
我们的业务定价取决于多个参数,现在我们想在 Django 中的现有设置中引入另一个可能的 M2M 参数。
为此,我们有一个现有的定价表,它对除price_field 之外的所有字段都有unique_together 约束。对示例中的通用/基于字母的命名表示歉意。
class PricingTable(models.Model):
a = models.ForeignKey(A, on_delete=models.CASCADE)
price = MoneyField()
b = ArrayField(models.CharField(choices=CHOICES))
c = models.ForeignKey(C, on_delete=models.CASCADE)
class Meta:
ordering = ("a",)
unique_together = ("a", "b", "c")
def validate_b(self):
# b can't be empty
if not len(self.b) >= 1:
raise ValueError
# each element in b needs to be unique
if not len(self.b) == len(set(self.b)):
raise ValueError
# each element in b needs to be unique together with a & c
for i in self.b:
query = PricingTable.objects.filter(
a=self.a, c=self.c, b__contains=[i]
).exclude(pk=self.pk)
if query.count() > 0:
raise ValueError
def save(self, *args, **kwargs):
self.validate_b()
return super().save(*args, **kwargs)
我想在此表中引入另一个参数,该参数必须与非价格参数(a、b 和c)一起唯一。
d = models.ManyToManyField("x.D", related_name="+")
列表b 中的每个元素与a 和c 一起必须是唯一的。
上述问题是validate_b 函数必须升级为可能具有繁重数据库查询的复杂函数。除此之外,Django 并没有提供一种直接的方式来确保多对多领域的独特团结。
那么,有没有我应该尝试的不同方法? through table 也许?但是,我应该在直通表中包含哪些所有字段?所有非价格字段?或者我是否应该停止梦想为d 提供多对多字段,并继续使用简单的外键方法,并在所有那些直截了当的字段上使用unique_together?
版本:
- Django 2.2
- postgres 11
如果需要,我可以将现有的 ArrayField 转换为一个简单的 CharField,这意味着更多的数据库行,只要我将所有独特的约束都放入数据库而不是每次都验证保存,这在某种程度上是可以的。
【问题讨论】:
标签: python django postgresql django-models database-design