Dans quelques rares cas, l'ORM de Django ne suffit plus. Lorsque votre requête est spécifique il existe plusieurs solutions que j'expose dans cet article illustré par le tri de liste.
Je reprends ici l'exemple de la dénormalisation. Dans le cas présent nous souhaitons récupérer une liste de critères triée par numéro (1, 2, 3). Si la vie était bien faite, un simple order_by sur l'attribut "numero" suffirait. Oui à condition que ce dernier soit un "integer" dans la base de données. Malheureusement l'attribut est un "CharField" / " Champ texte" et il est strictement interdit de corriger le type de champs (on stocke également des éléments de la formes IMA-2).
Deux étapes importantes :
- Convertir l'attribut "CharField" en attribut "Integer" sur demande
- Créer la méthode de tri
Convertir l'attribut en entier
Le numéro est stocké dans l'attribut "num" de notre modèle, nous souhaiterons le transformer en entier si c'est possible.
def get_num_in_integer(self): try: return int(self.num) except ValueError: return self.num
Trier / dénormaliser
criteria = sorted(criteria, key=lambda a: a.get_num_in_integer())
Petite ligne magique permettant de trier une liste de critère en fonction de son numéro, converti en entier à la volée
Prudence
Très bien, mais garder bien à l'esprit que la dénormalisation est à effectuer en cas de force majeure et surtout à la fin de vos vues, juste avant de passer le bébé au template.
Un queryset est une liste mais une liste n'est pas un queryset : Une fois passé dans la moulinette du "sorted" aucune méthode de queryset n'est disponible ! ce n'est plus un queryset mais une liste.. c'est compris ?
Utiliser une méthode de queryset sur une liste
Le titre est exagéré, il est préférable de dire "créer une méthode de liste".
Comment faire ?
IRC python-fr (flupke je crois) me répondIl faut sous classer mon ami
class MyList(list): __slots__ = () #optimisation ah oui ? def count(self): return len(self)
criteria = MyList(criteria)
Et voila côté template je peux ainsi utiliser aveuglement "criteria.count" comme si je manipulais un queryset.