Wofür wird `related_name` in Django verwendet?

390

Wofür ist das related_nameArgument nützlich für ManyToManyFieldund ForeignKeyFelder? Was bewirkt beispielsweise der folgende Code related_name='maps'?

class Map(db.Model):
    members = models.ManyToManyField(User, related_name='maps',
                                     verbose_name=_('members'))
zjm1126
quelle
12
@DanielRoseman Ist es für die Leistung oder die gute Praxis irgendwie gut, related_name = '+' zu verwenden, wenn keine Rückwärtsbeziehung erforderlich ist?
Lajarre
10
Ich wäre gespannt auf die Antwort auf die Frage von @ lajarre.
3cheesewheel
1
@lajarre - Ich gehe davon aus, dass sich die Leistung dadurch überhaupt nicht ändert. Ich musste es einmal mit FeinCMS-Inhaltstypen verwenden. Ich persönlich halte es für eine gute Praxis, immer das anzugeben. related_nameWenn Sie also wissen, dass Sie es nicht verwenden, ist es eine gute Sache. Das ist natürlich eine persönliche Meinung.
François Constant
@ 3cheesewheel es ist jetzt in den Dokumenten: docs.djangoproject.com/de/2.0/ref/models/fields/… + bedeutet, keine umgekehrte Beziehung zu erstellen
P. Myer Nore

Antworten:

530

Das related_nameAttribut gibt den Namen der umgekehrten Beziehung vom UserModell zurück zu Ihrem Modell an.

Wenn Sie nicht über eine angeben related_name, erstellt Django automatisch einen den Namen Ihres Modells mit dem Suffix _set, zum Beispiel User.map_set.all().

Wenn Sie noch angeben, zum Beispiel related_name=mapsauf dem UserModell, User.map_setwird immer noch funktionieren, aber die User.maps.Syntax ist offensichtlich etwas saubere und weniger klobig; Wenn Sie beispielsweise ein Benutzerobjekt hatten current_user, können Sie current_user.maps.all()alle Instanzen Ihres MapModells abrufen , zu denen eine Beziehung besteht current_user.

Die Django-Dokumentation enthält weitere Details.

Wogan
quelle
1
Okay, ich weiß, dass dies ein alter Beitrag ist. Aber ich versuche nur, das herauszufinden - was ist der + Trick am Ende des verwandten Namens? Was passiert zum Beispiel, wenn ich es related_name='maps+'im obigen Beispiel getan habe ?
Sidd
10
Wenn Sie das + hinzufügen, deaktiviert Django die Zuordnung
Josephmisiti
5
Für OneToOneField ist der Standardname für verwandte Fallnamen der Name einer kleinen Fallklasse. Wenn im angegebenen Beispiel beispielsweise Mitglieder OneToOnefield wären, funktioniert "User.map".
Ancho
wenn Sie angeben related_name, funktioniert _setimmer noch in django1.11 >?
Esir Kings
9
Ich benutze Django 2.1.3 und kann feststellen, dass diese exklusiv sind. Einmal related_nameangegeben, _setfunktioniert nicht mehr.
Stockersky
84

Das Hinzufügen zu vorhandenen antwortbezogenen Namen ist ein Muss, wenn das Modell 2 FKs enthält, die auf dieselbe Tabelle verweisen. Zum Beispiel bei Stücklisten

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

Wenn Sie also auf diese Daten zugreifen müssen, können Sie nur den zugehörigen Namen verwenden

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

Ansonsten funktioniert es nicht (zumindest konnte ich die Verwendung eines verwandten Namens bei 2 FKs nicht auf dieselbe Tabelle überspringen.)

Ilya Bibik
quelle
2
Sie müssen mindestens für einen von ihnen einen verwandten Namen auswählen. Der andere benötigt nicht unbedingt.
Csaba Toth
32
related_namesollte Plural sein. Weil ForeignKey-Beziehungen mehrere Objekte zurückgeben.
Mesut Tasci
11

Das related_nameArgument ist auch nützlich, wenn Sie komplexere verwandte Klassennamen haben. Wenn Sie beispielsweise eine Fremdschlüsselbeziehung haben:

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

Um auf UserMapDataFrameObjekte aus dem verwandten zuzugreifen User, wäre der Standardaufruf User.usermapdataframe_set.all(), der ziemlich schwer zu lesen ist.

Mit related_namekönnen Sie einen einfacheren oder besser lesbaren Namen angeben, um die umgekehrte Beziehung zu erhalten. In diesem Fall wäre user = models.ForeignKey(User, related_name='map_data')der Anruf dann , wenn Sie angeben User.map_data.all().

Daniel Holmes
quelle
3

Der zugehörige Namensparameter ist tatsächlich eine Option. Wenn wir es nicht einstellen, erstellt Django automatisch die andere Seite der Beziehung für uns. Im Fall des Kartenmodells hätte Django ein map_setAttribut erstellt, das den Zugriff über m.map_setin Ihrem Beispiel ermöglicht (m ist Ihre Klasseninstanz). Die Formel, die Django verwendet, ist der Name des Modells, gefolgt von der Zeichenfolge _set. Der zugehörige Namensparameter überschreibt daher einfach Djangos Standard, anstatt neues Verhalten bereitzustellen.

Abrar
quelle
0

prefetch_relatedVerwenden Sie diese Option, um Daten für viele zu viele und viele zu einer Beziehung vorab abzurufen. select_relatedbesteht darin, Daten aus einer Einzelwertbeziehung auszuwählen. Beide werden verwendet, um Daten aus ihren Beziehungen aus einem Modell abzurufen. Sie erstellen beispielsweise ein Modell und ein Modell, das eine Beziehung zu anderen Modellen hat. Wenn eine Anfrage kommt, werden Sie auch nach ihren Beziehungsdaten fragen und Django verfügt über sehr gute Mechanismen, um auf Daten aus ihrer Beziehung zuzugreifen, book.author.nameaber wenn Sie eine Liste von Modellen zum Abrufen ihrer Beziehungsdaten iterieren, erstellt Django jede Anfrage für jede einzelne Beziehungsdaten. Um dies zu überwinden, haben wir prefetchd_relatedundselected_related

Jamil Noyda
quelle