Django模型:为什么会出现名称冲突?

8

首先,我知道如何解决这个问题,我只是想了解为什么会发生这种情况。错误信息:

users.profile: 字段“address”的反向查询名称与相关字段“Address.profile”发生冲突。为“address”定义添加related_name参数。

而代码如下:

class Address(models.Model):
    country = fields.CountryField(default='CA')
    province = fields.CAProvinceField()
    city = models.CharField(max_length=80)
    postal_code = models.CharField(max_length=6)
    street1 = models.CharField(max_length=80)
    street2 = models.CharField(max_length=80, blank=True, null=True)
    street3 = models.CharField(max_length=80, blank=True, null=True)

class Profile(Address):
    user = models.ForeignKey(User, unique=True, related_name='profile')
    primary_phone = models.CharField(max_length=20)
    address = models.ForeignKey(Address, unique=True)

如果我理解正确,这行代码的意思是:

address = models.ForeignKey(Address, unique=True)

会导致在Address类中添加一个名为profile的属性。是什么创建了另一个"profile"名称?
如果我不需要反向名称怎么办?有没有一种方法可以禁用它?地址用于许多事情,因此大多数反向关系将为空。
有没有一种将地址字段复制到模型中而不是拥有一个单独的地址表的方法?没有Python继承(这没有意义,如果一个模型有2个地址,它不起作用)。
4个回答

25
Django文档中,它说:
如果您不希望Django创建反向关系,请将related_name设置为'+'。例如,这将确保User模型不会获得与此模型的反向关系:
user = models.ForeignKey(User, related_name='+')

但我从未自己尝试过...


1

我不确定哪里出现了错误的profile字段... 但是找到它的一种方法是:从Profile中暂时删除address = models.ForeignKey(…),然后在./manage.py shell中执行from ... import Address,看看Address.profile会告诉你什么。

我认为没有任何官方的方法可以仅继承其他模型的字段而不使用继承... 但是你可以像这样伪造它(其中SourceModel是例如AddressTargetModel是例如Profile):

for field in SourceModel._meta.fields:
    TargetModel.add_to_class(field.name, copy.deepcopy(field))

(这是来自Django的ModelBase __new__实现


按照你说的做了。AttributeError: type object 'Address' has no attribute 'profile'。实际上...不给它命名,它就不再报错了。我不确定我改了什么 >.< 也许它被缓存了一段时间或者其他什么原因。 - mpen

0

我认为禁用反向名称是不可能的。

我刚刚快速地在代码中进行了grep,看起来没有任何逻辑可以绕过在相关模型上设置related_name字段的设置。


0
例如:只需添加“+”
class GeneralConfiguration(models.Model):

created_at = models.DateTimeField(editable=False, default=settings.DEFAULT_DATE)
updated_at = models.DateTimeField(editable=False, default=settings.DEFAULT_DATE)
created_by = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, null=True, on_delete=models.PROTECT, related_name='+')
updated_by = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, null=True, on_delete=models.PROTECT, related_name='+')

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接