具有未继承约束的 Django 模型抽象模型:'constraints' 指的是字段 'xxx',它不是模型 'Foo' 的本地字段
Django model abstract model with constrains not being inherited: 'constraints' refers to field 'xxx' which is not local to model 'Foo'
我正在使用 Django 3.2
我遇到了一个似乎是错误的奇怪行为; ABC 中定义的约束中使用的字段不会被子 类.
继承
myapp/models.py
class BaseFoo(models.Model):
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE,related_name='%(class)s_content_type')
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
user = models.ForeignKey(User, blank=False, null=False, on_delete=models.CASCADE,related_name='%(class)s')
created = models.DateTimeField(auto_now_add=True)
class Meta:
abstract = True
constraints = [
models.UniqueConstraint(fields=['content_object', 'user'], name="'%(class)s_unique"),
]
class Foo(BaseFoo):
class Meta(BaseFoo.Meta):
abstract = False
当我 makemigrations
时没问题,但是,当我尝试迁移架构时(`python manage.py 迁移),我收到以下错误:
myapp.Foo: (models.E016) 'constraints' refers to field 'content_object' which is not local to model 'Foo'.
HINT: This issue may be caused by multi-table inheritance.
为什么Foo没有继承父类ABC明确定义的字段? - 我该如何解决这个问题(假设这不是错误)?
1. 不能使用 GenericForeignKey
in UniqueConstraint
, because a GenericForeignKey 不是普通的字段对象。而在 UniqueConstraint
中使用 content_type
和 object_id
,这等同于 content_object
:
class Meta:
abstract = True
constraints = [
models.UniqueConstraint(
<b>fields=['content_type', 'object_id', 'user']</b>,
<b>name="%(app_label)s_%(class)s_user_unique")</b>,
]
参见Django Docs:
Due to the way GenericForeignKey
is implemented, you cannot use
such fields directly with filters (filter() and exclude(), for
example) via the database API. Because a GenericForeignKey
isn’t a normal field object.
Likewise, GenericForeignKey
does not appear in ModelForms.
2. 根据Django Docs in abstract base classes related_name
必须包含'%(app_label)s' 和 '%(class)s'。并且您应该始终为字段指定唯一的反向名称和查询名称。
content_type = models.ForeignKey(
ContentType, on_delete=models.CASCADE,
related_name='<b>%(app_label)s_%(class)s</b>_content_types',
<b>related_query_name='%(app_label)s_%(class)s_content_type'</b>,
)
user = models.ForeignKey(
User, blank=False, null=False,
on_delete=models.CASCADE,
related_name='<b>%(app_label)s_%(class)s</b>_users',
related_query_name='%(app_label)s_%(class)s_user',
)
If you are using related_name or related_query_name on a
ForeignKey or ManyToManyField, you must always specify a unique reverse name and query name for the field. This would normally
cause a problem in abstract base classes, since the fields on this
class are included into each of the child classes, with exactly the
same values for the attributes (including related_name and
related_query_name) each time.
To work around this problem, when you are using related_name or
related_query_name in an abstract base class (only), part of the value
should contain '%(app_label)s' and '%(class)s'.
我正在使用 Django 3.2
我遇到了一个似乎是错误的奇怪行为; ABC 中定义的约束中使用的字段不会被子 类.
继承myapp/models.py
class BaseFoo(models.Model):
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE,related_name='%(class)s_content_type')
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
user = models.ForeignKey(User, blank=False, null=False, on_delete=models.CASCADE,related_name='%(class)s')
created = models.DateTimeField(auto_now_add=True)
class Meta:
abstract = True
constraints = [
models.UniqueConstraint(fields=['content_object', 'user'], name="'%(class)s_unique"),
]
class Foo(BaseFoo):
class Meta(BaseFoo.Meta):
abstract = False
当我 makemigrations
时没问题,但是,当我尝试迁移架构时(`python manage.py 迁移),我收到以下错误:
myapp.Foo: (models.E016) 'constraints' refers to field 'content_object' which is not local to model 'Foo'. HINT: This issue may be caused by multi-table inheritance.
为什么Foo没有继承父类ABC明确定义的字段? - 我该如何解决这个问题(假设这不是错误)?
1. 不能使用 GenericForeignKey
in UniqueConstraint
, because a GenericForeignKey 不是普通的字段对象。而在 UniqueConstraint
中使用 content_type
和 object_id
,这等同于 content_object
:
class Meta:
abstract = True
constraints = [
models.UniqueConstraint(
<b>fields=['content_type', 'object_id', 'user']</b>,
<b>name="%(app_label)s_%(class)s_user_unique")</b>,
]
参见Django Docs:
Due to the way
GenericForeignKey
is implemented, you cannot use such fields directly with filters (filter() and exclude(), for example) via the database API. Because aGenericForeignKey
isn’t a normal field object.Likewise,
GenericForeignKey
does not appear in ModelForms.
2. 根据Django Docs in abstract base classes related_name
必须包含'%(app_label)s' 和 '%(class)s'。并且您应该始终为字段指定唯一的反向名称和查询名称。
content_type = models.ForeignKey(
ContentType, on_delete=models.CASCADE,
related_name='<b>%(app_label)s_%(class)s</b>_content_types',
<b>related_query_name='%(app_label)s_%(class)s_content_type'</b>,
)
user = models.ForeignKey(
User, blank=False, null=False,
on_delete=models.CASCADE,
related_name='<b>%(app_label)s_%(class)s</b>_users',
related_query_name='%(app_label)s_%(class)s_user',
)
If you are using related_name or related_query_name on a ForeignKey or ManyToManyField, you must always specify a unique reverse name and query name for the field. This would normally cause a problem in abstract base classes, since the fields on this class are included into each of the child classes, with exactly the same values for the attributes (including related_name and related_query_name) each time.
To work around this problem, when you are using related_name or related_query_name in an abstract base class (only), part of the value should contain '%(app_label)s' and '%(class)s'.