web-dev-qa-db-fra.com

Quel est l'ordre par défaut d'une liste renvoyée par un appel de filtre Django?

Question courte
Quel est l'ordre par défaut d'une liste renvoyée par un appel de filtre Django lorsqu'elle est connectée à une base de données PostgreSQL?

Contexte
De mon propre aveu, j'avais fait une mauvaise hypothèse au niveau de la couche application en ce que l'ordre dans lequel une liste est renvoyée serait constante, c'est-à-dire sans utiliser 'order_by'. La liste des éléments que je recherchais n'est pas dans l'ordre alphabétique ou dans tout autre ordre délibéré. On pensait qu'il resterait dans le même ordre que celui dans lequel ils ont été ajoutés à la base de données.

Cette hypothèse s'est vérifiée pour des centaines de requêtes, mais un échec a été signalé par mon application lorsque la commande a changé sans le savoir. À ma connaissance, aucun de ces enregistrements n'a été touché pendant cette période, car je suis la seule personne à gérer la base de données. Pour ajouter à la confusion, lors de l'exécution de l'application Django sur Mac OS X, cela fonctionnait toujours comme prévu, mais sur Win XP, cela a changé l'ordre. (Notez que les centaines de requêtes mentionnées étaient sous Win XP).

Tout aperçu serait utile car je n'ai rien trouvé dans la documentation Django ou PostgreSQL qui expliquait les différences entre les systèmes d'exploitation.

Exemple d'appel

required_tests = Card_Test.objects.using(get_database()).filter(name__icontains=key)

MODIFIER
Après avoir parlé avec certains de mes collègues aujourd'hui, j'avais trouvé la même réponse que Björn Lindqvist.

Avec le recul, je comprends vraiment pourquoi cela est mal fait si souvent. L'un des avantages de l'utilisation d'un ORM Django, sqlalchemy ou autre est que vous pouvez écrire des commandes sans avoir à connaître ou à comprendre (en détail) la base de données à laquelle il est connecté. Certes, il se trouve que j'ai été l'un de ces utilisateurs. Cependant, le revers de la médaille est que sans connaître en détail la base de données, les erreurs de débogage comme celle-ci sont assez gênantes et potentiellement catastrophiques.

52
Adam Lewis

Il y a PAS D'ORDRE PAR DÉFAUT, un point qui ne peut pas être suffisamment souligné parce que tout le monde le fait mal.

Une table dans une base de données n'est pas une table html ordinaire, c'est un ensemble non ordonné de tuples. Cela surprend souvent les programmeurs habitués à MySQL, car dans cette base de données particulière, l'ordre des lignes est souvent prévisible car il ne tire pas parti de certaines techniques d'optimisation avancées. Par exemple, il n'est pas possible de savoir quelles lignes seront retournées ou leur ordre dans l'une des requêtes suivantes:

select * from table limit 10
select * from table limit 10 offset 10
select * from table order by x limit 10

Dans la dernière requête, l'ordre n'est prévisible que si toutes les valeurs de la colonne x sont uniques. Le SGBDR est libre de renvoyer toutes les lignes dans n'importe quel ordre tant qu'il satisfait aux conditions de l'instruction select.

Bien que vous puissiez ajouter un ordre par défaut au niveau Django, ce qui l'amène à ajouter une clause order by à chaque requête non ordonnée:

class Table(models.Model):
    ...
    class Meta:
        ordering = ['name']

Notez que cela peut être un frein aux performances, si pour une raison quelconque, vous n'avez pas besoin de lignes ordonnées.

71
Björn Lindqvist