¿Para qué se utiliza `related_name` en Django?

392

¿Cuál es el related_nameargumento útil para on ManyToManyFieldy ForeignKeyfields? Por ejemplo, dado el siguiente código, ¿cuál es el efecto de related_name='maps'?

class Map(db.Model):
    members = models.ManyToManyField(User, related_name='maps',
                                     verbose_name=_('members'))
zjm1126
fuente
12
@DanielRoseman ¿De alguna manera es bueno para el rendimiento o las buenas prácticas usar related_name = '+' cuando la relación hacia atrás no es necesaria?
lajarre
10
Me gustaría saber la respuesta a la pregunta de @ lajarre.
3cheesewheel
1
@lajarre: supongo que eso no cambiará el rendimiento en absoluto. Tuve que usarlo una vez con los tipos de contenido FeinCMS. Personalmente, creo que es una buena práctica especificar siempre, related_nameasí que si sabes que no lo usarás, supongo que es algo bueno. Esa es una opinión personal, por supuesto.
François Constant
@ 3cheesewheel está en los documentos ahora: docs.djangoproject.com/en/2.0/ref/models/fields/… + significa no crear una relación inversa
P. Myer Nore

Respuestas:

532

El related_nameatributo especifica el nombre de la relación inversa desde el Usermodelo hasta su modelo.

Si no especifica un related_name, Django crea automáticamente uno usando el nombre de su modelo con el sufijo _set, por ejemplo User.map_set.all().

Si lo especifica, por ejemplo, related_name=mapsen el Usermodelo, User.map_setseguirá funcionando, pero la User.maps.sintaxis es obviamente un poco más limpia y menos torpe; así, por ejemplo, si tuviera un objeto de usuario current_user, podría usarlo current_user.maps.all()para obtener todas las instancias de su Mapmodelo con las que tenga relación current_user.

La documentación de Django tiene más detalles.

Wogan
fuente
1
Bien, sé que esta es una publicación antigua. Pero solo estoy tratando de resolver esto: ¿cuál es el truco + al final del nombre relacionado? Por ejemplo, ¿qué sucede si lo hice related_name='maps+'en el ejemplo anterior?
Sidd
10
si agrega el +, django desactiva el mapeo
josephmisiti
55
para OneToOneField default_name relacionado será un pequeño nombre de clase de caso. Por ejemplo, en el ejemplo dado, si los miembros serían OneToOnefield, entonces "User.map" funcionará.
ancho
si lo especifica related_name, ¿ _settodavía funciona en django1.11 >??
Esir Kings
99
Uso Django 2.1.3 y puedo notar que son exclusivos. Una vez que related_namese especifica, _setya no funciona.
stockersky
85

Para agregar a la respuesta existente, el nombre relacionado es imprescindible en caso de que haya 2 FK en el modelo que apunten a la misma tabla. Por ejemplo en caso de lista de materiales

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

Entonces, cuando tenga que acceder a estos datos, solo puede usar el nombre relacionado

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

De lo contrario, no funciona (al menos no pude omitir el uso del nombre relacionado en el caso de 2 FK en la misma tabla).

Ilya Bibik
fuente
2
Tienes que elegir un nombre relacionado al menos para uno de ellos. El otro no requiere necesariamente.
Csaba Toth
32
related_namedebe ser plural. Porque las relaciones ForeignKey devuelven múltiples objetos.
Mesut Tasci
11

El related_nameargumento también es útil si tiene nombres de clase relacionados más complejos. Por ejemplo, si tiene una relación de clave externa:

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

Para acceder a los UserMapDataFrameobjetos relacionados User, la llamada predeterminada sería User.usermapdataframe_set.all(), que es bastante difícil de leer.

El uso de le related_namepermite especificar un nombre más simple o más legible para obtener la relación inversa. En este caso, si especifica user = models.ForeignKey(User, related_name='map_data'), la llamada sería entonces User.map_data.all().

Daniel Holmes
fuente
3

El parámetro de nombre relacionado es en realidad una opción. Si no lo configuramos, Django crea automáticamente el otro lado de la relación para nosotros. En el caso del modelo Map, Django habría creado un map_setatributo, permitiendo el acceso a través de m.map_seten su ejemplo (m es su instancia de clase). La fórmula que usa Django es el nombre del modelo seguido de la cadena _set. El parámetro de nombre relacionado simplemente anula el valor predeterminado de Django en lugar de proporcionar un nuevo comportamiento.

Abrar
fuente
0

prefetch_relatedse utiliza para obtener datos previos para datos de relación de Muchos a muchos y de muchos a uno select_relatedes seleccionar datos de una relación de valor único. Ambos se utilizan para obtener datos de sus relaciones de un modelo. Por ejemplo, crea un modelo y un modelo que tiene una relación con otros modelos. Cuando llegue una solicitud, también consultará sus datos de relación y Django tiene mecanismos muy buenos para acceder a los datos de su relación, book.author.namepero cuando itera una lista de modelos para recuperar sus datos de relación, Django crea cada solicitud para cada dato de relación. Para superar esto tenemos prefetchd_relatedyselected_related

Jamil Noyda
fuente