Что такое `related_name`, используемый в Django?
Что такое аргумент related_name
, полезный для полей ManyToManyField
и ForeignKey
? Например, учитывая следующий код, каков эффект related_name='maps'
?
class Map(db.Model):
members = models.ManyToManyField(User, related_name='maps',
verbose_name=_('members'))
Ответы
Ответ 1
Атрибут related_name
указывает имя обратного отношения от модели User
к вашей модели.
Если вы не укажете related_name
, Django автоматически создает имя, используя имя вашей модели с суффиксом _set
, например User.map_set.all()
.
Если вы укажете, например, related_name=maps
в модели User
, User.map_set
все равно будет работать, но синтаксис User.maps.
, очевидно, немного чист и менее неуклюж; например, если у вас есть пользовательский объект current_user
, вы можете использовать current_user.maps.all()
, чтобы получить все экземпляры вашей модели Map
, которые имеют отношение к current_user
.
Документация Django содержит более подробную информацию.
Ответ 2
Чтобы добавить к существующему ответному имени, необходимо, чтобы в модели было указано 2 FK, которые указывают на одну и ту же таблицу. Например, в случае Билля материала
@with_author
class BOM(models.Model):
name = models.CharField(max_length=200,null=True, blank=True)
description = models.TextField(null=True, blank=True)
tomaterial = models.ForeignKey(Material, related_name = 'tomaterial')
frommaterial = models.ForeignKey(Material, related_name = 'frommaterial')
creation_time = models.DateTimeField(auto_now_add=True, blank=True)
quantity = models.DecimalField(max_digits=19, decimal_places=10)
Итак, когда вам нужно будет получить доступ к этим данным
вы можете использовать только связанное имя
bom = material.tomaterial.all().order_by('-creation_time')
Он не работает иначе (по крайней мере, я не смог пропустить использование связанного имени в случае 2 FK в ту же таблицу.)
Ответ 3
Аргумент related_name
также полезен, если у вас есть более сложные имена связанных классов. Например, если у вас есть отношение внешнего ключа:
class UserMapDataFrame(models.Model):
user = models.ForeignKey(User)
Чтобы получить доступ UserMapDataFrame
объектам UserMapDataFrame
от связанного User
, вызов по умолчанию будет User.usermapdataframe_set.all()
, который довольно трудно прочитать.
Использование related_name
позволяет вам указать более простое или более разборчивое имя, чтобы получить обратную связь. В этом случае, если вы укажете user = models.ForeignKey(User, related_name='map_data')
, вызовом будет User.map_data.all()
.
Ответ 4
Параметр связанного имени фактически является опцией. Если мы не установим его, Django автоматически создаст для нас другую сторону отношения. В случае модели карты Django создал бы атрибут map_set
, разрешая доступ через m.map_set
в вашем примере (m - ваш экземпляр класса). Формула Django использует имя модели, за которой следует строка _set
. Таким образом, связанный параметр имени просто переопределяет значение по умолчанию Djangos, а не обеспечивает новое поведение.
Ответ 5
prefetch_related
используется для данных предварительной выборки для данных отношения "многие ко многим" и "многие к одному".
select_related
предназначен для выбора данных из отношения с одним значением. Оба они используются для извлечения данных из их отношений из модели. Например, вы строите модель и модель, которая связана с другими моделями. Когда приходит запрос, вы также запрашиваете данные об их отношениях, и у Django есть очень хорошие механизмы для доступа к данным из их отношений, например, book.author.name
, но когда вы повторяете список моделей для извлечения данных об их отношениях, Django создает каждый запрос для каждого отдельного отношения данных. Для преодоления этого у нас есть prefetchd_related
и selected_related