Ich benutze ein ManyToManyField mit einer 'durch' Klasse und dies führt zu einer Menge von Abfragen beim Abrufen einer Liste von Dingen. Ich frage mich, ob es einen effizienteren Weg gibt.Wie kann ich Django ManyToMany ‚durch‘ Abfragen effizienter machen?
Zum Beispiel sind hier einige vereinfachte Klassen Bücher und ihre verschiedenen Autoren beschreiben, die durch eine Rollenklasse geht (zu definieren Rollen wie „Editor“, „Illustrator“, etc):
class Person(models.Model):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
@property
def full_name(self):
return ' '.join([self.first_name, self.last_name,])
class Role(models.Model):
name = models.CharField(max_length=50)
person = models.ForeignKey(Person)
book = models.ForeignKey(Book)
class Book(models.Model):
title = models.CharField(max_length=255)
authors = models.ManyToManyField(Person, through='Role')
@property
def authors_names(self):
names = []
for role in self.role_set.all():
person_name = role.person.full_name
if role.name:
person_name += ' (%s)' % (role.name,)
names.append(person_name)
return ', '.join(names)
Wenn ich rufe Book.authors_names(), dann kann ich einen String etwas wie diese:
John Doe (Herausgeber), Fred Bloggs, Billy Bob (Illustrator)
Es funktioniert gut, aber es gibt eine Abfrage, um die Rollen für das Buch zu erhalten, und dann eine weitere Abfrage für jede Person. Wenn ich eine Liste von Büchern anzeigen lasse, ergeben sich viele Anfragen.
Gibt es eine Möglichkeit, dies effizienter zu tun, in einer einzigen Abfrage pro Buch, mit einem Join? Oder ist der einzige Weg, etwas wie batch-select zu verwenden?
(für Bonuspunkte ... meine Codierung von authors_names() sieht ein bisschen klobig - ist es eine Möglichkeit, es elegante Python-esque zu machen?)
‚Python-artige‘ in der Regel für Vergleiche zu Monty Python vorbehalten: das Wort für Sie suchen ist ‚Pythonic‘. –
@daniel: +1 für die korrekte Verwendung von 'Pythonic', obwohl die Verwendung von 'Python-esque' bedeuten kann, dass der Autor versucht, den Code ein bisschen lustiger zu machen ... –
Danke für die Korrektur. Ich werde mich jedoch von nun an bemühen, meinen Code nicht nur korrekter, sondern auch lustiger zu machen. –