在 Django 中,如何向现有模型添加 join table 关系?

In Django, how do I add a join table relation to an existing model?

我正在使用 Python 3.9 和 Django 3.2。我有这些模型。第二个是第一个

的连接 table
class Coop(models.Model):
    objects = CoopManager()
    name = models.CharField(max_length=250, null=False)
    types = models.ManyToManyField(CoopType, blank=False)
    addresses = models.ManyToManyField(Address, through='CoopAddressTags')
 

class CoopAddressTags(models.Model):
    # Retain referencing coop & address, but set "is_public" relation to NULL
    coop = models.ForeignKey(Coop, on_delete=models.SET_NULL, null=True)
    address = models.ForeignKey(Address, on_delete=models.SET_NULL, null=True)
    is_public = models.BooleanField(default=True, null=False)

我想在我的第一个模型中实际引用连接 table,所以我添加了

address_tags = models.ManyToManyField('CoopAddressTags')

喜欢

class Coop(models.Model):
    objects = CoopManager()
    name = models.CharField(max_length=250, null=False)
    types = models.ManyToManyField(CoopType, blank=False)
    address_tags = models.ManyToManyField('CoopAddressTags')
    addresses = models.ManyToManyField(Address, through='CoopAddressTags')

但是当我 运行 生成偏头痛的脚本时出现此错误

$ python manage.py makemigrations directory
SystemCheckError: System check identified some issues:

ERRORS:
directory.Coop.address_tags: (fields.E303) Reverse query name for 'directory.Coop.address_tags' clashes with field name 'directory.CoopAddressTags.coop'.
    HINT: Rename field 'directory.CoopAddressTags.coop', or add/change a related_name argument to the definition for field 'directory.Coop.address_tags'.

我不清楚这意味着什么或如何解决它。目标是当我有一个“Coop”对象时,我可以引用它的地址以及这些地址是否是 public.

发生这种情况的原因是因为 address_tagsCoopAddressTags 这意味着现在 ManyToManyFieldrelated_query_name=… parameter [Django-doc] 的默认值是针对 Address 模型具有 'coop' 作为值,这与 CoopAddressTags.

中的 coop 关系同名

但是造型很奇葩。很可能您只想在 CoopAddress 之间定义一个 ManyToManyFieldCoopAddressTagsjunction table [wiki]。因此,您将其建模为您最初的尝试。

如果您需要 through=… 模型中的项目,您可以通过以下方式访问它:

<i>my_coop</i><strong>.coopaddresstags_set.all()</strong>

或者您可以过滤:

Coop.objects.filter(<strong>coopaddresstags__is_public=True</strong>, adresses=<em>my_address</em>)

然后,这将检索所有 Coop,其中 my_address 和 [=19] 之间存在 public 关系=].