回答:
Djangoクエリセットは遅延しています。つまり、特に結果を要求した場合にのみ、クエリがデータベースにヒットします。
したがって、クエリの結果を出力または実際に使用するまで、データベースにアクセスせずにさらにフィルタリングできます。
以下に示すように、コードは1つのSQLクエリのみを実行して、最後の10項目のみをフェッチします。
In [19]: import logging
In [20]: l = logging.getLogger('django.db.backends')
In [21]: l.setLevel(logging.DEBUG)
In [22]: l.addHandler(logging.StreamHandler())
In [23]: User.objects.all().order_by('-id')[:10]
(0.000) SELECT "auth_user"."id", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."password", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."is_superuser", "auth_user"."last_login", "auth_user"."date_joined" FROM "auth_user" ORDER BY "auth_user"."id" DESC LIMIT 10; args=()
Out[23]: [<User: hamdi>]
実際、私はこれLIMIT 10
がデータベースに発行されるので、スライスはPythonではなくデータベースで発生すると思います。
詳細については、limiting-querysetsを参照してください。
質問の解決策はDjango 1.7では機能せず、エラーが発生します:「スライスが取得された後はクエリを並べ替えることができません」
ドキュメントによると、https: //docs.djangoproject.com/en/dev/topics/db/queries/#limited-querysets Pythonスライス構文の「step」パラメータを強制すると、クエリが評価されます。それはこのように機能します:
Model.objects.all().order_by('-id')[:10:1]
それでも、制限がSQLまたはPythonで実行されるのか、返された結果配列全体がスライスされるのかと思います。巨大なリストをアプリケーションメモリに取得するのはよくありません。
他の有用な回答への追加と観察として、[:10]
スライスとして実際に行うと、最後の10ではなく、リストの最初の10要素が返されることに注意する価値があり ます...
最後の10を取得するには、[-10:]
代わりに行う必要があります(ここを参照)。これはorder_by('-id')
、-
を使用して要素を逆にするのを避けるのに役立ちます。
Product.objects.filter(~Q(price=0))[-5:]
でも同じエラーが発生します:「負のインデックス作成はサポートされていません。」