À quoi sert «related_name» dans Django?

392

Quel est l' related_nameargument utile pour les champs on ManyToManyFieldet ForeignKey? Par exemple, étant donné le code suivant, quel est l'effet de related_name='maps'?

class Map(db.Model):
    members = models.ManyToManyField(User, related_name='maps',
                                     verbose_name=_('members'))
zjm1126
la source
12
@DanielRoseman Est-il en quelque sorte bon pour les performances ou les bonnes pratiques d'utiliser related_name = '+' lorsqu'une relation en amont n'est pas nécessaire?
lajarre
10
Je serais curieux de connaître la réponse à la question de @ lajarre.
3cheesewheel
1
@lajarre - Je suppose que cela ne changera pas du tout les performances. J'ai dû l'utiliser une fois avec les types de contenu FeinCMS. Personnellement, je pense que c'est une bonne pratique de toujours spécifier le related_namedonc si vous savez que vous ne l'utiliserez pas, je suppose que c'est une bonne chose. C'est une opinion personnelle bien sûr.
François Constant
@ 3cheesewheel c'est dans les docs maintenant: docs.djangoproject.com/en/2.0/ref/models/fields/… + signifie ne pas créer de relation inverse
P. Myer Nore

Réponses:

532

L' related_nameattribut spécifie le nom de la relation inverse du Usermodèle vers votre modèle.

Si vous ne spécifiez pas de related_name, Django en crée automatiquement un en utilisant le nom de votre modèle avec le suffixe _set, par exemple User.map_set.all().

Si vous ne spécifiez, par exemple related_name=mapssur le Usermodèle, User.map_setcontinuera à fonctionner, mais la User.maps.syntaxe est évidemment un peu plus propre et moins maladroits; ainsi, par exemple, si vous aviez un objet utilisateur current_user, vous pouvez utiliser current_user.maps.all()pour obtenir toutes les instances de votre Mapmodèle qui ont une relation avec current_user.

La documentation Django contient plus de détails.

Wogan
la source
1
D'accord, je sais que c'est un vieux post. Mais j'essaie juste de comprendre cela - quelle est l'astuce + à la fin du nom associé? Par exemple, que se passe-t-il si je l'ai fait related_name='maps+'dans l'exemple ci-dessus?
Sidd
10
si vous ajoutez le +, django désactive le mappage
josephmisiti
5
pour OneToOneField, le nom associé par défaut sera un petit nom de classe de cas. Par exemple, dans l'exemple donné, si les membres seraient OneToOnefield, "User.map" fonctionnera.
ancho
si vous spécifiez related_name, fonctionne _settoujours dans django1.11 >??
Esir Kings
9
J'utilise Django 2.1.3 et je peux noter que ceux-ci sont exclusifs. Une fois related_namespécifié, _setne fonctionne plus.
stockersky
85

Ajouter au nom existant lié à la réponse est un must dans le cas où 2 FK dans le modèle pointent vers la même table. Par exemple en cas de nomenclature

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

Ainsi, lorsque vous devrez accéder à ces données, vous ne pouvez utiliser que le nom associé

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

Cela ne fonctionne pas autrement (au moins, je n'ai pas pu ignorer l'utilisation du nom associé dans le cas de 2 FK dans la même table.)

Ilya Bibik
la source
2
Vous devez choisir un nom associé au moins pour l'un d'eux. L'autre n'exige pas nécessairement.
Csaba Toth du
32
related_namedevrait être pluriel. Parce que les relations ForeignKey renvoient plusieurs objets.
Mesut Tasci
11

L' related_nameargument est également utile si vous avez des noms de classe liés plus complexes. Par exemple, si vous avez une relation de clé étrangère:

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

Pour accéder à des UserMapDataFrameobjets à partir de la relation User, l'appel par défaut serait User.usermapdataframe_set.all(), ce qui est assez difficile à lire.

L'utilisation de related_namevous permet de spécifier un nom plus simple ou plus lisible pour obtenir la relation inverse. Dans ce cas, si vous spécifiez user = models.ForeignKey(User, related_name='map_data'), l'appel serait alors User.map_data.all().

Daniel Holmes
la source
3

Le paramètre de nom associé est en fait une option. Si nous ne le définissons pas, Django crée automatiquement l'autre côté de la relation pour nous. Dans le cas du modèle Map, Django aurait créé un map_setattribut, permettant l'accès via m.map_setdans votre exemple (m étant votre instance de classe). La formule utilisée par Django est le nom du modèle suivi de la chaîne _set. Le paramètre de nom associé remplace donc simplement la valeur par défaut de Django plutôt que de fournir un nouveau comportement.

Abrar
la source
0

prefetch_relatedutiliser pour les données de prélecture pour les données de relation plusieurs à plusieurs et plusieurs à un. select_relatedconsiste à sélectionner des données à partir d'une relation de valeur unique. Ces deux éléments sont utilisés pour extraire des données de leurs relations à partir d'un modèle. Par exemple, vous créez un modèle et un modèle qui a une relation avec d'autres modèles. Lorsqu'une demande arrive, vous interrogerez également leurs données de relation et Django dispose de très bons mécanismes pour accéder aux données de leur relation comme book.author.namemais lorsque vous parcourez une liste de modèles pour récupérer leurs données de relation, Django crée chaque demande pour chaque donnée de relation. Pour remédier à cela , nous n'avons prefetchd_relatedetselected_related

Jamil Noyda
la source