Как в 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.