Для чего используется `related_name` в Django?

263

Что такое аргумент related_name, полезный для полей ManyToManyField и ForeignKey? Например, учитывая следующий код, каков эффект related_name='maps'?

class Map(db.Model):
    members = models.ManyToManyField(User, related_name='maps',
                                     verbose_name=_('members'))
  • 11
    @DanielRoseman Хорошо ли для производительности или хорошей практики использовать related_name = '+', когда обратное отношение не требуется?
  • 9
    Мне было бы интересно узнать ответ на вопрос @ lajarre.
Показать ещё 2 комментария
Теги:
many-to-many
foreign-key-relationship

4 ответа

347
Лучший ответ

Атрибут 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 содержит более подробную информацию.

  • 1
    Хорошо, я знаю, что это старый пост. Но я просто пытаюсь понять это - что за хитрость + в конце связанного названия? Например, что произойдет, если я сделал related_name='maps+' в примере выше?
  • 7
    если вы добавите +, Django отключит отображение
Показать ещё 3 комментария
51

Чтобы добавить к существующему ответному имени, необходимо, чтобы в модели было указано 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 в ту же таблицу.)

  • 2
    Вы должны выбрать related_name хотя бы для одного из них. Другой не требует.
  • 15
    related_name должно быть во множественном числе. Потому что отношения ForeignKey возвращают несколько объектов.
2

Параметр связанного имени фактически является опцией. Если мы не установим его, Django автоматически создаст для нас другую сторону отношения. В случае модели карты Django создал бы атрибут map_set, разрешая доступ через m.map_set в вашем примере (m - ваш экземпляр класса). Формула Django использует имя модели, за которой следует строка _set. Таким образом, связанный параметр имени просто переопределяет значение по умолчанию Djangos, а не обеспечивает новое поведение.

0

Аргумент 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().

Ещё вопросы

Сообщество Overcoder
Наверх
Меню