Do czego służy nazwa „nazwa_powiązana” w Django?

390

Jaki related_nameargument jest przydatny dla pól ManyToManyFieldi ForeignKeypól? Na przykład, biorąc pod uwagę następujący kod, jaki jest efekt related_name='maps'?

class Map(db.Model):
    members = models.ManyToManyField(User, related_name='maps',
                                     verbose_name=_('members'))
zjm1126
źródło
12
@DanielRoseman Czy to jest dobre dla wydajności lub dobrej praktyki, aby używać related_name = '+', gdy relacja wsteczna nie jest konieczna?
lajarre
10
Byłbym ciekawy odpowiedzi na pytanie @ lajarre.
3cheesewheel,
1
@lajarre - Zakładam, że w ogóle nie zmieni to wydajności. Musiałem go użyć raz z typami zawartości FeinCMS. Osobiście uważam, że dobrą praktyką jest zawsze sprecyzowanie, related_namewięc jeśli wiesz, że go nie użyjesz, myślę, że to dobra rzecz. To oczywiście osobista opinia.
François Constant
@ 3cheesewheel jest teraz w dokumentacji: docs.djangoproject.com/en/2.0/ref/models/fields/… + oznacza, że ​​nie twórz odwrotnej relacji
P. Myer Nore

Odpowiedzi:

529

related_nameAtrybut określa nazwę odwrotnej zależności od Usermodelu z powrotem do swojego modelu.

Jeśli nie zostanie określony related_name, Django automatycznie tworzy jedną używając nazwy swojego modelu z przyrostkiem _set, np User.map_set.all().

Jeśli tak , np. related_name=mapsW Usermodelu, User.map_setnadal będzie działać, ale User.maps.składnia jest oczywiście nieco bardziej przejrzysta i mniej niezręczna; na przykład, jeśli masz obiekt użytkownika current_user, możesz użyć, current_user.maps.all()aby uzyskać wszystkie instancje Mapmodelu, które są powiązane current_user.

Dokumentacja Django zawiera więcej szczegółów.

Wogan
źródło
1
Okej, wiem, że to stary post. Ale próbuję to rozgryźć - jaka jest sztuczka + na końcu powiązanej nazwy? Na przykład, co się stanie, jeśli zrobię to related_name='maps+'w powyższym przykładzie?
Sidd
10
jeśli dodasz +, django wyłącza mapowanie
josephmisiti
5
dla OneToOneField domyślna nazwa powiązana będzie nazwą klasy małej litery. Na przykład w podanym przykładzie, jeśli członkami będą OneToOnefield, wówczas „User.map” będzie działać.
ancho
jeśli określisz related_name, _setnadal działa w django1.11 >?
Esir Kings
9
Używam Django 2.1.3 i mogę zauważyć, że są one wyłączne. Raz related_nameokreślony, _setjuż nie działa.
stockersky
82

Aby dodać do istniejącej nazwy związanej z odpowiedzią, należy koniecznie w przypadku, gdy w modelu znajdują się 2 FK, które wskazują tę samą tabelę. Na przykład w przypadku Zestawienia materiałów

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

Kiedy będziesz musiał uzyskać dostęp do tych danych, możesz używać tylko powiązanych nazw

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

Nie działa inaczej (przynajmniej nie byłem w stanie pominąć użycia nazwy pokrewnej w przypadku 2 FK do tej samej tabeli).

Ilya Bibik
źródło
2
Musisz wybrać nazwę pokrewną przynajmniej dla jednego z nich. Drugi nie wymaga tego.
Csaba Toth
32
related_namepowinno być w liczbie mnogiej. Ponieważ relacje ForeignKey zwracają wiele obiektów.
Mesut Tasci
10

related_nameArgumentem jest również przydatna, gdy masz więcej skomplikowanych nazw pokrewnych klas. Na przykład, jeśli masz relację klucza obcego:

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

Aby uzyskać dostęp do UserMapDataFrameobiektów z powiązanych User, domyślnym wywołaniem byłoby User.usermapdataframe_set.all(), co jest dość trudne do odczytania.

Korzystanie z related_namepozwala określić prostszą lub bardziej czytelną nazwę, aby uzyskać odwrotną zależność. W takim przypadku, jeśli określisz user = models.ForeignKey(User, related_name='map_data'), połączenie będzie wtedy User.map_data.all().

Daniel Holmes
źródło
3

Powiązany parametr nazwy jest właściwie opcją. Jeśli go nie ustawimy, Django automatycznie utworzy dla nas drugą stronę relacji. W przypadku modelu mapy Django utworzyłby map_setatrybut umożliwiający dostęp m.map_setw twoim przykładzie (m jest instancją klasy). Formuła używana przez Django to nazwa modelu, po której następuje łańcuch _set. Powiązany parametr name w ten sposób po prostu zastępuje domyślny parametr Django, a nie zapewnia nowe zachowanie.

Abrar
źródło
0

prefetch_relatedużyj do pobrania danych dla danych relacji wiele do wielu i wiele do jednego. select_relatedjest wybranie danych z relacji jednej wartości. Oba są używane do pobierania danych z ich relacji z modelu. Na przykład budujesz model i model, który ma związek z innymi modelami. Kiedy nadejdzie żądanie, zapytasz również o dane ich relacji, a Django ma bardzo dobre mechanizmy dostępu do danych z ich relacji, tak jak book.author.namepodczas iteracji listy modeli do pobierania danych ich relacji, Django tworzy każde żądanie dla każdego pojedynczego danych relacji. Aby temu zaradzić, mamy prefetchd_relatediselected_related

Jamil Noyda
źródło