2009-06-02 5 views
6

Je récupère les 5 dernières lignes d'un modèle Foo qui est trié par un champ datetime.django - réorganiser le jeu de requête après l'avoir découpé

qs = Foo.objects.all()[:5] 

Dans l'étape suivante, je veux réorganiser la queryset par d'autres critères (en fait, par le même champ datetime dans le sens inverse). Mais réorganiser après une tranche n'est pas autorisé. reverse() annule le premier ordre, en me donnant un jeu de différences. Y a-t-il un moyen d'accomplir ce que je veux sans créer une liste à partir du jeu de requête et de faire l'ordre de l'utiliser?

Répondre

10

Non, il n'y a aucun moyen de le faire. order_by est une opération sur la base de données, mais lorsque vous découpez un ensemble de requêtes, il est évalué et ne retourne pas dans la base de données après cela.

Cela ressemble à vous connaissez déjà la solution, cependant: exécutez reversed() sur le qs évalué.

qs = reversed(Foo.objects.all()[:5]) 
+0

Donc, je n'ai rien manqué. Merci. – shanyu

+0

J'ai eu le même problème et j'ai suivi la suggestion de Daniel mais j'ai trouvé que je ne pouvais pas utiliser la méthode count sur le jeu de requête – thchand

+0

Impossible de trouver la référence à reverse() dans docs python, les liens que vous pouvez fournir? –

13

order_by vous donne l'ordre SQL dans la base de données. Vous utilisez déjà cela, et ensuite trancher dessus. À ce stade, les résultats sont récupérés en mémoire. Si vous voulez changer leur ordre, vous devez utiliser le tri Python en mémoire pour le faire, et non le tri ORM dans la base de données.

Dans votre cas, Daniel a déjà donné la meilleure solution: puisque vous voulez simplement faire un tri selon le même domaine, mais dans l'autre ordre, juste inverser la liste que vous avez:

qs = Foo.objects.all()[:5] 
objs = reversed(qs) 

Si vous aviez voulait trier par un autre domaine, alors vous utilisez la fonction triée() avec une fonction clé personnalisée:

qs = Foo.objects.all()[:5] 
objs = sorted(qs, key=lambda o: o.some_other_field) 
+0

Oui, je sais que order_by est un ordre DB. Mais j'ai trouvé intéressant qu'un reverse() (la méthode queryset) après que la tranche fonctionne, et qu'elle réexécute la requête, donnant des résultats inattendus. – shanyu

+0

Lorsque vous extrayez les résultats d'un jeu de requête, il s'agit toujours d'un jeu de requête valide. Si vous le modifiez (par exemple en ajoutant reverse()), il le réévaluera. –

1

réponse tardive, mais tout a fonctionné pour moi:

import random 
sorted(queryset[:10], key=lambda x: random.random()) 
Questions connexes