Что такое `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