6

Для чего используется параметр related_name?

7

Какова цель аргумента related_name для полей ManyToManyField и ForeignKey? Например, в приведённом ниже коде каково воздействие related_name='maps'?

class Map(db.Model):
    members = models.ManyToManyField(User, related_name='maps',
                                     verbose_name=_('members'))

5 ответ(ов)

1

Чтобы дополнить существующий ответ, стоит отметить, что использование related_name обязательно в случае, если в модели есть два внешних ключа, указывающих на одну и ту же таблицу. Например, в случае с "Нормативной документацией":

@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)

Таким образом, когда вам потребуется получить доступ к данным, вы сможете использовать related_name:

bom = material.tomaterial.all().order_by('-creation_time')

В противном случае обращение к данным не сработает (по крайней мере, у меня не получилось обойтись без использования related_name, если есть два внешних ключа к одной таблице).

0

Аргумент related_name также полезен, если у вас есть более сложные названия связанных классов. Например, если у вас есть отношение с внешним ключом:

class UserMapDataFrame(models.Model):
    user = models.ForeignKey(User)

Чтобы получить объекты UserMapDataFrame из связанного объекта User, по умолчанию используется вызов User.usermapdataframe_set.all(), что довольно сложно читать.

Использование related_name позволяет вам указать более простое или более понятное имя для доступа к обратному отношению. В данном случае, если вы укажете user = models.ForeignKey(User, related_name='map_data'), вызов будет выглядеть как User.map_data.all().

0

Суть вашего вопроса такова.

У вас есть модели Map и User, и вы определили ManyToManyField в модели Map. Если вы хотите получить доступ к участникам карты, то вы можете использовать map_instance.members.all(), так как вы определили поле members. Однако, если вам нужно получить все карты, в которых участвует пользователь, то каким образом вы можете это сделать?

По умолчанию Django предоставляет вам возможность использовать user_instance.modelname_set.all(), и в вашем случае это будет user.map_set.all().

Тем не менее, использование maps будет предпочтительнее, чем использование map_set.

Поле related_name предоставляет вам возможность указать Django, как вы собираетесь получать доступ к модели Map из модели User, или, в общем, как вы можете получить доступ к обратным моделям. Это и является основной целью создания полей ManyToMany и использования ORM в таком контексте.

0

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

0

prefetch_related используется для предварительной выборки данных в отношениях "многие ко многим" и "многие к одному". select_related предназначен для выборки данных в отношениях с одним значением. Оба этих метода используются для получения данных из связанных моделей.

Например, вы создаете модель, которая имеет отношения с другими моделями. Когда поступает запрос, вам также нужно получить данные о связанных моделях. Django предоставляет отличные механизмы для доступа к данным из этих отношений, такие как book.author.name. Однако, когда вы перебираете список объектов модели для получения их связанных данных, Django выполняет отдельный запрос для каждой связи, что может быть неэффективно.

Чтобы избежать этого, мы можем использовать prefetch_related и select_related. select_related работает через JOIN и подходит для отношений "один к одному" и "многие к одному", в то время как prefetch_related создает отдельные запросы и объединяет их на уровне Python, что делает его более подходящим для отношений "многие ко многим" и "многие к одному". Использование этих методов позволяет оптимизировать количество запросов к базе данных и ускорить работу приложения.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь