Je veux prendre les 10 dernières instances d'un modèle et avoir ce code:
Model.objects.all().order_by('-id')[:10]
Est-il vrai que vous devez d'abord prendre toutes les instances, puis n'en prendre que 10 dernières? Existe-t-il une méthode plus efficace?
Réponses:
Les ensembles de requêtes Django sont paresseux. Cela signifie qu'une requête atteindra la base de données uniquement lorsque vous demanderez spécifiquement le résultat.
Donc, jusqu'à ce que vous imprimiez ou utilisiez réellement le résultat d'une requête, vous pouvez filtrer davantage sans accès à la base de données.
Comme vous pouvez le voir ci-dessous, votre code n'exécute qu'une seule requête SQL pour récupérer uniquement les 10 derniers éléments.
la source
En fait, je pense que le
LIMIT 10
serait délivré à la base de données afin que le découpage ne se produise pas en Python mais dans la base de données.Voir limitation-querysets pour plus d'informations.
la source
Il semble que la solution de la question ne fonctionne plus avec Django 1.7 et génère une erreur: "Impossible de réorganiser une requête une fois qu'une tranche a été prise"
Selon la documentation https://docs.djangoproject.com/en/dev/topics/db/queries/#limiting-querysets forçant le paramètre «step» de la syntaxe de tranche Python évalue la requête. Cela fonctionne de cette façon:
Je me demande toujours si la limite est exécutée dans des tranches SQL ou Python, le tableau de résultats entier retourné. Il ne sert à rien de récupérer d'énormes listes dans la mémoire de l'application.
la source
Oui. Si vous souhaitez récupérer un sous-ensemble limité d'objets, vous pouvez le faire avec le code ci-dessous:
Exemple:
Le début 0 est facultatif, donc
Le code ci-dessus renvoie les 10 premières instances.
la source
Comme ajout et observation aux autres réponses utiles, il convient de noter qu'en réalité, le fait
[:10]
de trancher renvoie les 10 premiers éléments de la liste , pas les 10 derniers ...Pour obtenir les 10 derniers, vous devez faire à la
[-10:]
place (voir ici ). Cela vous évitera d'utiliserorder_by('-id')
avec le-
pour inverser les éléments.la source
Product.objects.filter(~Q(price=0))[-5:]
me cause la même erreur: "L'indexation négative n'est pas prise en charge."