我正在为我的django应用程序创建一个抽象模型,SrdObject
。我的模型的一个特征是它有一对字段,这些字段加在一起必须是唯一的:"name"和外键"module"。
这是我拥有的一个例子
class SrdObject(models.Model):
name = models.CharField(max_length=50)
slug_name = models.SlugField(max_length=75, unique=True)
active = models.BooleanField(default=True)
module = models.ForeignKey(Module, on_delete=models.CASCADE, related_name='%(class)s', blank=False, null=False, default='default')
class Meta:
unique_together = ['name', 'module']
ordering = ['name']
abstract = True
这似乎工作正常,但是 unique_together
属性已被 django 标记为已弃用(见这里(,所以我将其更改为
class Meta:
constraints = [
models.UniqueConstraint(fields=['name', 'module'], name='unique-in-module')
]
ordering = ['name']
abstract = True
这不起作用,因为名称字段必须是唯一的,并且由于这是一个抽象类,因此在多个模型上重复约束。
我也试过
models.UniqueConstraint(fields=['name', 'module'], name='{}-unique-in-module'.format(model_name))
但显然这属于范围问题,所以我尝试了装饰器方法
def add_unique_in_module_constraint(cls):
cls._meta.constraints = [
models.UniqueConstraint(fields=['name', 'module'], name='unique-in-module')
]
return cls
@add_unique_in_module_constraint
class SrdObject(models.Model):
class Meta:
ordering = ['name']
abstract = True
但这似乎没有任何作用。
那么我该如何创建一个模型。抽象模型中的唯一约束,如果每个约束都需要一个唯一的名称属性?
最新更新
从第 3 版开始,您终于可以通过指定插值来做到这一点:
Changed in Django 3.0:
Interpolation of '%(app_label)s' and '%(class)s' was added.
例:
UniqueConstraint(fields=['room', 'date'], name='%(app_label)s_unique_booking')
OLD (Django <3.0(
你不能那样做,对我来说同样的问题,太难过了......
来源: 姜戈文档
抽象基类中的约束
必须始终为约束指定唯一名称。因此,通常不能在抽象基类上指定约束,因为 Meta.constraints 选项由子类继承,每次属性(包括名称(的值完全相同。相反,直接在子类上指定约束选项,为每个约束提供唯一的名称。
我采用了这个模型设置:
class Module(models.Model):
pass
class SrdObject(models.Model):
name = models.CharField(max_length=50)
slug_name = models.SlugField(max_length=75, unique=True)
active = models.BooleanField(default=True)
module = models.ForeignKey(Module, on_delete=models.CASCADE, related_name='%(class)s', blank=False, null=False, default='default')
class Meta:
constraints = [
models.UniqueConstraint(fields=['name', 'module'], name='unique-in-module')
]
ordering = ['name']
abstract = True
class SrdObjectA(SrdObject):
pass
class SrdObjectB(SrdObject):
pass
然后运行这些测试:
class TestSrdObject(TestCase):
@classmethod
def setUpTestData(cls):
cls.module = Module.objects.create()
SrdObjectA.objects.create(name='A', module=cls.module)
def test_unique_applies_to_same_model(self):
with self.assertRaises(IntegrityError):
SrdObjectA.objects.create(name='A', module=self.module)
def test_unique_does_not_apply_to_different_model(self):
self.assertTrue(SrdObjectB.objects.create(name='A', module=self.module))
他们过去了。也许我仍然错过了您遇到的问题?