2016-05-29 12 views
0

Angenommen, ich habe das in meinem models.py folgenden verschachtelt:Django Shortcut Fremdschlüssel

class Book: 
    pass 

class Part: 
    book = models.ForeignKey(Book) 

class Chapter: 
    part = models.ForeignKey(Part) 
    number = models.IntegerField() 

Ich möchte

book = Book.objects.get(id=someID) 
chapters = Book.chapters.get(number=4) 

tun Was für eine saubere Art und Weise, dies zu tun? Ich dachte an einen Manager in der Buchklasse, aber es scheint für diesen Fall nicht zu funktionieren.

Natürlich könnte ich eine Methode get_chapters auf Klassenbuch implementieren, aber ich möchte dies vermeiden.

irgendwelche Ideen?

+0

https://docs.djangoproject.com/de/1.9/topics/db/queries/#backwards-related-objects – eustass

Antwort

0

Mithilfe von related_name-Argumenten für FK-Felder, gekoppelt mit prefetch_related für ein Abfrage-Set, können Sie alle Informationen zu einem Buch mit minimalem Performance-Treffer abrufen (jeder prefetch_related-Parameter ruft eine separate Abfrage auf).

class Book: 
    pass 

class Part: 
    book = models.ForeignKey(Book, related_name="parts") 

class Chapter: 
    part = models.ForeignKey(Part, related_name="chapters") 
    number = models.IntegerField() 

# fetch a book and all related info w/ only 2 db hits 
book = Book.objects.first().prefetch_related("parts","parts__chapters") 
print(book.parts.all()) # returns all parts for book 
for part in book.parts.all(): 
    print part.chapters.all() 

Sie können dies auch in einer Vorlage tun.

Für die leistungsfähigste Lösung speichern Sie jedoch auch einen FK, um aus dem Kapitel zu buchen. Dies kann leicht durch Überschreiben der Speichermethode erfolgen.

class Chapter: 
    part = models.ForeignKey(Part, related_name="part_chapters") 
    number = models.IntegerField() 
    book = models.ForeignKey(Book, related_name="chapters", null=True, blank=True) # allow null/blank values; will be populated in save method 
    def save(self, *args, **kwargs): 
     self.book = self.part.book 
     super(Chapter, self).save(*args, **kwargs) 

>>> book = Book.objects.first().prefetch_related("parts","chapters") 
>>> print(book.parts.all()) # returns all parts for book 
>>> print(book.chapters.all()) 
Verwandte Themen