Per cosa viene utilizzato `related_name` in Django?


391

Qual è l' related_nameargomento utile per on ManyToManyFielde ForeignKeyfield? Ad esempio, dato il seguente codice, qual è l'effetto di related_name='maps'?

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

12
@DanielRoseman È in qualche modo utile per le prestazioni o le buone pratiche usare related_name = '+' quando non è necessaria una relazione all'indietro?
lajarre,

10
Sarei curioso di sapere la risposta alla domanda di @ lajarre.
3cheesewheel

1
@lajarre - Presumo che non cambierà affatto le prestazioni. Ho dovuto usarlo una volta con i tipi di contenuto FeinCMS. Personalmente penso che sia una buona pratica specificare sempre, related_namequindi se sai che non lo userai, suppongo sia una buona cosa. Questa è un'opinione personale, ovviamente.
François Constant

@ 3cheesewheel è ora nei documenti: docs.djangoproject.com/en/2.0/ref/models/fields/… + significa che non creare una relazione inversa
P. Myer Nore,

Risposte:


531

L' related_nameattributo specifica il nome della relazione inversa dal Usermodello al modello.

Se non specifichi a related_name, Django ne crea automaticamente uno usando il nome del tuo modello con il suffisso _set, per esempio User.map_set.all().

Se non si specifica, ad esempio related_name=mapssul Usermodello User.map_setcontinuerà a funzionare, ma la User.maps.sintassi è ovviamente un po 'più pulito e meno goffo; quindi, ad esempio, se si dispone di un oggetto utente current_user, è possibile utilizzare current_user.maps.all()per ottenere tutte le istanze del Mapmodello a cui è correlata current_user.

La documentazione di Django ha maggiori dettagli.


1
Ok, so che questo è un vecchio post. Ma sto solo cercando di capirlo: qual è il + trucco alla fine del nome correlato? Ad esempio, cosa succede se ho fatto related_name='maps+'nell'esempio sopra?
Sidd

10
se aggiungi +, django disabilita la mappatura
josephmisiti il

5
per OneToOneField il nome_relativo predefinito sarà un nome di classe minuscolo. Ad esempio, nell'esempio fornito, se i membri fossero OneToOnefield, "User.map" funzionerà.
Ancho,

se si specifica related_name, funziona _setancora in django1.11 >??
Esir Kings,

9
Uso Django 2.1.3 e posso notare che sono esclusivi. Una volta related_namespecificato, _setnon funziona più.
stockersky,

84

È necessario aggiungere un nome correlato alla risposta esistente nel caso in cui nel modello siano presenti 2 FK che puntano alla stessa tabella. Ad esempio in caso di distinta base

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

Pertanto, quando dovrai accedere a questi dati, puoi utilizzare solo il nome correlato

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

In caso contrario non funziona (almeno non sono riuscito a saltare l'uso del nome correlato in caso di 2 FK nella stessa tabella).


2
Devi scegliere un nome_relativo almeno per uno di essi. L'altro non richiede necessariamente.
Csaba Toth,

32
related_namedovrebbe essere al plurale. Perché le relazioni ForeignKey restituiscono più oggetti.
Mesut Tasci,

11

L' related_nameargomento è utile anche se si hanno nomi di classe correlati più complessi. Ad esempio, se si dispone di una relazione chiave esterna:

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

Al fine di accedere agli UserMapDataFrameoggetti dai relativi User, la chiamata predefinita sarebbeUser.usermapdataframe_set.all() , che è piuttosto difficile da leggere.

L'uso di related_nameconsente di specificare un nome più semplice o più leggibile per ottenere la relazione inversa. In questo caso, se si specifica user = models.ForeignKey(User, related_name='map_data'), la chiamata sarà quindi User.map_data.all().


3

Il parametro relativo al nome è in realtà un'opzione. Se non lo impostiamo, Django crea automaticamente l'altro lato della relazione per noi. Nel caso del modello Map, Django avrebbe creato un map_setattributo, consentendo l'accesso tramite m.map_setnel tuo esempio (essendo m la tua istanza di classe). La formula utilizzata da Django è il nome del modello seguito dalla stringa _set. Il parametro relativo al nome sostituisce quindi semplicemente il valore predefinito di Django anziché fornire un nuovo comportamento.


0

prefetch_relatedutilizzare per precaricare i dati per dati di relazione Many to many e many to one. select_relatedè selezionare i dati da una relazione a valore singolo. Entrambi vengono utilizzati per recuperare i dati dalle loro relazioni da un modello. Ad esempio, si crea un modello e un modello che ha una relazione con altri modelli. Quando arriva una richiesta, esegui anche una query per i loro dati di relazione e Django ha ottimi meccanismi per accedere ai dati della loro relazione come, book.author.namema quando si itera un elenco di modelli per recuperare i loro dati di relazione, Django crea ogni richiesta per ogni singolo dato di relazione. Per ovviare a questo abbiamo prefetchd_relatedeselected_related

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.