Magazine Internet

Django : Trier vos utilisateurs par ordre alphabétique

Publié le 15 septembre 2011 par Samuel Martin

Il existe probablement d'autres solutions. Dans cet article je vous donne les clés pour réussir à trier correctement les utilisateurs par nom et prénom. L'exercice est assez simple lorsque l'utilisateur a renseigné correctement son identité, c'est à dire "Nom et Prénom". Cela devient plus chaotique, quand un seul des champs est renseigné.

Liste factice

  1. LEGRAND Simon - [email protected]
  2. THOMAS Robert - [email protected]
  3. PETIT Catherine - [email protected]
  4. BONNET Georges - [email protected]
  5. THOMAS Alfred - [email protected]

Alfred et Robert ne se connaissent pas

Solution de fortune

User.objects.filter(...).order_by('last_name', 'first_name') Soyons honnête cette requête suffit dans la majorité des cas. Mais que fait elle ? Elle trie par ordre alphabétique par nom puis prénom. Donc appliquée sur la liste ci-dessus cela nous donne :

  1. BONNET Georges - [email protected]
  2. LEGRAND Simon - [email protected]
  3. PETIT Catherine - [email protected]
  4. THOMAS Alfred - [email protected]
  5. THOMAS Robert - [email protected]

Maintenant imaginons le pire. Mr LEGRAND Simon et Mme Catherine ne renseignent plus leur nom de famille. On obtient ainsi :

  1. Simon - [email protected]
  2. Catherine - [email protected]
  3. BONNET Georges - [email protected]
  4. THOMAS Alfred - [email protected]
  5. THOMAS Robert - [email protected]

Oui mais moi je veux voir Simon et Catherine à leur place c'est à dire en se basant sur le "S" de Simon et le "C" de Catherine.

Trois solutions pour trier la liste

Trois solutions, un seule retenue. Il n'y a pas de meilleure, tout dépend de votre besoin.

  1. Utiliser Raw Sql pour fusionner la colonne "last_name" et "first_name" et effectuer un tri sur cette fusion
  2. Créer un nouveau champs dans la DB, celui ci étant la fusion de "last_name" et de "first_name"
  3. Dénormaliser la requête et utiliser une méthode métier
  • Première solution : Performance moyenne et obligation d'écrire en SQL. Requête simple si cela provient directement du models "User", beaucoup plus compliqué si c'est une liste d'utilisateur extraite d'un projet. (project.get_users) .. avec potentiellement une multitude de filtres.
  • Deuxième solution : Performance haute, obligation de créer un nouvel attribut dans User Profile, surcharger la méthode save(). Si votre base est en place, vous devez générer cette colonne. Oblige également à passer par get_profile(). Le plus pratique serait de directement modifier la table "User".
  • Troisième solution: Performance moyenne, vous devez ajouter une méthode au models User (User redéfini par Meta Class) et écrire la dénormalisation.

J'ai choisi la troisième solution, l'historique du projet facilitait le choix. En effet User était déjà redéfini par MetaClass donc finalement une méthode, une dénormalisation et c'était dans la poche.

La méthode métier sur User

Nommez-la comme vous voulez.
def get_full_name_inverse(self):
        return (("%s %s") % (self.last_name.capitalize(), self.first_name.capitalize())).strip()
  • Cette méthode fusionne le nom et le prénom. Elle supprime les espace en début et fin indésirable. Très important pour le tri !
  • Cette méthode ajoute une belle majuscule au nom et au prénom. L'intérêt est uniquement visuel

La dénormalisation

 users = User.objects.filter(...) 
 users = sorted(users, key=lambda a: a.get_full_name_inverse())

Et voici la version qui permet de gérer les caractères accentués.

import locale
users = User.objects.filter(...) 
locale.setlocale(locale.LC_ALL, "fr_FR.UTF-8")
users = sorted(users, cmp=locale.strcoll, key=lambda a: a.get_full_name_inverse())

On obtient ainsi la liste suivante :

  1. BONNET Georges - [email protected]
  2. Catherine - [email protected]
  3. Simon - [email protected]
  4. THOMAS Alfred - [email protected]
  5. THOMAS Robert - [email protected]

Retour à La Une de Logo Paperblog

A propos de l’auteur


Samuel Martin 21 partages Voir son profil
Voir son blog

l'auteur n'a pas encore renseigné son compte l'auteur n'a pas encore renseigné son compte

Magazine