【发布时间】:2021-09-30 04:01:25
【问题描述】:
我有两个这样的模型:
class Group(...):
pass
class Identifier(...):
value = models.CharField(...)
group = models.ForeignKey('Group', ..., related_named = 'identifiers')
我该怎么做:
- 将
Group限制为最多只有4 个Identifiers? - 确保最多 4 个
Identifiers(标识符的值)的任意组合在所有Groups中都是唯一的?
对于第 2 部分,这里是扁平化 Groups 表的示例:
row | id__0__val | id__1__val | id__2__val | id__3__val
--- | ---------- | ---------- | ---------- | ----------
0 | abc | 123 | xyz | 456
1 | abc | 123 | xyz | - <-- valid (nulls are okay)
2 | 123 | abc | xyz | 456 <-- invalid (same combo as row 0)
以前我尝试过(类似的)这个,但它看起来很乱,功能有限,我不确定它是否能工作:
class Group(...):
id__0 = models.OneToOneField('Identifier', blank = True, null = True, ...)
id__1 = models.OneToOneField('Identifier', blank = True, null = True, ...)
id__2 = models.OneToOneField('Identifier', blank = True, null = True, ...)
id__3 = models.OneToOneField('Identifier', blank = True, null = True, ...)
class Meta:
unique_together = ('id__0__value', 'id__1__value', 'id__2__value', 'id__3__value')
处理这种约束的更好方法是什么?
【问题讨论】:
-
我不确定它是否适用于反向关系(或像
count这样的聚合),但您是否尝试过使用 Check 约束(参见 docs.djangoproject.com/en/3.2/ref/models/constraints/…)?您也没有指定它,但是如果您使用的是 Postgres,您可能会摆脱 ArrayField 而不是以硬编码的方式枚举关系,即使它也不是很干净? (docs.djangoproject.com/en/3.2/ref/contrib/postgres/fields/…) -
不,我以前没有见过检查约束,是的,我正在使用 Postgres - ArrayField 如何解决其中一些问题?
-
您可以限制 ArrayField 的大小(即限制为 4 个项目),并且您可以对其执行检查。但缺点是:它不能真正保存相关字段引用,并且最终会出现弱匹配。最后,我认为这个缺点是相当严重的。可悲的是,Django 似乎不允许处理关系列表上的唯一性。顺便提一句。我认为您的第二个解决方案也可以,因为 Postgres 将 NULL 视为不同的值(虽然不是空白,所以
blank=False应该是更好的 IMO) -
您需要数据库来强制执行此约束吗?还是仅在 Python 中处理验证就足够了?
标签: python django django-models