J'utilise un ManyToManyField avec une classe 'through', ce qui entraîne de nombreuses requêtes lors de l'extraction d'une liste de choses. Je me demande s'il y a un moyen plus efficace.Comment rendre les requêtes Django ManyToMany 'through' plus efficaces?
Par exemple voici quelques classes simplifiées décrivant livres et leurs nombreux auteurs, qui passe par une classe de rôle (pour définir les rôles comme « éditeur », « 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)
Si je l'appelle Book.authors_names() alors je peux obtenir quelque chose comme une chaîne ceci:
John Doe (Sous la direction de), Fred Bloggs, Billy Bob (Illustrations)
Cela fonctionne bien, mais il fait une requête pour obtenir les rôles pour le livre, puis une autre requête pour chaque personne. Si j'affiche une liste de livres, cela ajoute beaucoup de questions.
Existe-t-il un moyen de le faire plus efficacement, dans une seule requête par livre, avec une jointure? Ou est le seul moyen d'utiliser quelque chose comme batch-select?
(Pour les points bonus ... mon codage de authors_names() semble un peu maladroit - est-il un moyen de le rendre plus élégant Python-esque?)
Python-esque »est habituellement réservé aux comparaisons de Monty Python: le mot que vous cherchez est 'Pythonic'. –
@daniel: +1 pour l'utilisation correcte de 'pythonic', bien que l'utilisation de 'python-esque' puisse impliquer que l'auteur cherche à rendre le code un peu plus drôle ... –
Merci pour la correction. Cependant, je m'efforcerai désormais de rendre mon code non seulement plus correct mais aussi plus drôle. –