2010-04-15 16 views
192

Quel est l'argument related_name utile pour les champs ManyToManyField et ForeignKey? Par exemple, étant donné le code suivant, quel est l'effet de related_name='maps'?À quoi sert «related_name» dans Django?

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

@DanielRoseman Est-ce que c'est bon pour la performance ou une bonne pratique d'utiliser related_name = '+' quand la relation en arrière n'est pas nécessaire? – lajarre

+7

Je serais curieux de connaître la réponse à la question de @ lajarre. – 3cheesewheel

+1

@lajarre - Je suppose que cela ne changera rien à la performance. 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_name', donc 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. –

Répondre

275

L'attribut related_name spécifie le nom de la relation inverse du modèle User à 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 spécifiez, par ex. related_name=maps sur le modèle User, User.map_set fonctionnera toujours, mais la syntaxe User.maps. est évidemment un peu plus propre et moins maladroit; Par exemple, si vous avez un objet utilisateur current_user, vous pouvez utiliser current_user.maps.all() pour obtenir toutes les instances de votre modèle Map ayant une relation avec current_user.

Le Django documentation a plus de détails.

+1

D'accord, je sais que c'est un vieux post. Mais j'essaie juste de comprendre cela - quel est le truc + à la fin du nom associé? Par exemple, que se passe-t-il si j'ai fait 'related_name = 'maps +'' dans l'exemple ci-dessus? – Sidd

+4

Si vous ajoutez le +, django désactive le mappage – josephmisiti

+2

pour OneToOneField default_name sera un nom de classe de petite taille. Par exemple dans l'exemple donné si les membres seraient OneToOnefield alors "User.map" fonctionnera. – ancho

32

Ajouter un nom associé à une réponse existante est un must dans le cas où 2 FK dans le modèle pointent vers la même table. Par exemple, dans le cas du projet de loi de matériel

@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 le nom lié

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

Il ne fonctionne pas autrement (au moins je n'étais pas en mesure pour passer l'utilisation du nom associé dans le cas de 2 FK à la même table.)

+1

Vous devez choisir un related_name au moins pour l'un d'entre eux. L'autre ne l'exige pas nécessairement. –

+3

'related_name' devrait être au pluriel. Parce que les relations ForeignKey renvoient plusieurs objets. –