Для чого використовується "related_name" в Django?


390

Для чого related_nameкорисний аргумент для ManyToManyFieldта на ForeignKeyполях? Наприклад, з урахуванням наступного коду, на що впливає related_name='maps'?

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

12
@DanielRoseman Чи якось добре для продуктивності чи належної практики використовувати related_name = '+', коли зворотне відношення не потрібно?
lajarre

10
Мені буде цікаво дізнатися відповідь на запитання @ lajarre.
3cheesewheel

1
@lajarre - Я припускаю, що це зовсім не змінить продуктивність. Мені довелося використовувати це один раз із типами вмісту FeinCMS. Особисто я вважаю, що це завжди добре вказувати, related_nameтому якщо ви знаєте, що ви не будете використовувати його, я думаю, це добре. Це, звичайно, особиста думка.
Франсуа Констант

@ 3cheesewheel зараз у документах: docs.djangoproject.com/en/2.0/ref/models/fields/… + означає, що не створювати зворотного відношення
П. Myer Nore,

Відповіді:


529

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.

Документація Джанго має більше деталей.


1
Гаразд, я знаю, що це стара публікація. Але я просто намагаюся розібратися в цьому - який + трюк в кінці пов’язаного імені? Наприклад, що станеться, якщо я це зробив related_name='maps+'у наведеному вище прикладі?
Сідд

10
якщо ви додасте +, django відключає відображення
josephmisiti

5
для OneToOneField default_name за замовчуванням буде невеликим назвою класу регістру. Наприклад, у наведеному прикладі, якщо членами буде OneToOnefield, тоді "User.map" буде працювати.
анчо

якщо ви вказали related_name, чи _setвсе ще працює django1.11 >??
Есір Кінгз

9
Я використовую Django 2.1.3 і можу зазначити, що вони є ексклюзивними. Як тільки related_nameзазначено, _setбільше не працює.
stockersky

82

Додавання до існуючого імені, пов'язаного з відповіддю, є обов'язковим у випадку, якщо в моделі є 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
Ви повинні вибрати ім'я пов’язаного_менця принаймні для одного з них. Інший не вимагає необхідності.
Csaba Toth

32
related_nameмає бути множиною. Тому що відносини ForeignKey повертають кілька об'єктів.
Mesut Tasci

10

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().


3

Пов'язаний параметр імені - це фактично параметр. Якщо ми цього не встановимо, Джанго автоматично створить іншу сторону відносин для нас. У випадку з моделлю Map, Django створив би map_setатрибут, що дозволить отримувати доступ m.map_setу вашому прикладі (я - ваш екземпляр класу). Формула, яку використовує Джанго, - це назва моделі, за якою слідує рядок _set. Пов'язаний параметр імені, таким чином, просто замінює за замовчуванням Django, а не надає нову поведінку.


0

prefetch_relatedвикористовувати для попереднього вибору даних для даних багатьох для багатьох і багатьох до одного. select_relatedполягає у виборі даних із одного значення значення. Обидва вони використовуються для отримання даних про їх відносини з моделі. Наприклад, ви будуєте модель та модель, яка має стосунки з іншими моделями. Коли надходить запит, ви також запитаєте їх дані про стосунки, і у Django є дуже хороші механізми доступу до даних із їхніх стосунків, як, book.author.nameале коли ви ітератуєте список моделей для отримання даних про їх стосунки, Django створює кожен запит для кожного окремого даного стосунку. Для подолання цього у нас є prefetchd_relatedіselected_related

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.