Как в Django добавить отношение присоединяемой таблицы к существующей модели?

Я использую Python 3.9 и Django 3.2. У меня есть такие модели. Вторая является join-таблицей для первой

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)

Я хотел бы фактически ссылаться на таблицу join в моей первой модели, поэтому я добавил

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", я мог ссылаться на его адреса и на то, являются ли эти адреса публичными.

Причина, по которой это происходит, заключается в том, что address_tags в CoopAddressTags, что означает, что теперь значение по умолчанию для параметра related_query_name=… [Django-doc] из ManyToManyField, который нацелен на модель Address, имеет 'coop' в качестве значения, и это то же имя, что и отношение coop в CoopAddressTags.

But the modeling is very odd. Very likely you only want to define a single ManyToManyField between Coop and Address, with the CoopAddressTags as junction table [wiki]. You thus model this as in your initial attempt.

Если вам нужны элементы из модели through=…, вы получаете доступ к ним с помощью:

my_coop.coopaddresstags_set.all()

или вы можете фильтровать с помощью:

Coop.objects.filter(coopaddresstags__is_public=True, adresses=my_address)

Тогда, например, будут получены все Coop, для которых существует открытое отношение между my_address и этим Coop.

Вернуться на верх