web-dev-qa-db-ja.com

クエリセット内の要素のインデックスを取得します

私はQuerySetを持っているので、それをqsと呼びましょう。これは、この問題とは関係のない属性によって順序付けられています。次に、オブジェクトがあります。それをobjと呼びます。ここで、objqsefficientlyとして可能なインデックスを知りたいと思います。 Pythonから.index()を使用したり、各オブジェクトをqsと比較してobjをループしたりできることはわかっていますが、何が最良かこれを実行する方法?私は高いパフォーマンスを探しており、それが私の唯一の基準です。

WindowsでPython 2.6.2をDjango 1.0.2と組み合わせて使用​​します。

37
Deniz Dogan

DjangoのQuerySetsは実際にはジェネレーターであり、リストではありません(詳細については、 DjangoのQuerySetsに関するドキュメント を参照してください)。
そのため、要素のインデックスを取得するショートカットはありません。単純な反復がそれを行うための最良の方法だと思います。

手始めに、可能な限り最も簡単な方法で(反復のように)要件を実装します。あなたが本当にパフォーマンスの問題を抱えているなら、私はいくつかの異なるアプローチを使用します。
いずれの場合でも、そのようなトリックが必要であることが確実にわかっている場合は、そのようなトリックをできるだけ遅くすることをお勧めします。
更新:いくつかのSQLステートメントを直接使用して行番号を取得したい場合があります(ただし、DjangoのORMはこれをネイティブでサポートしていないため、生のSQLクエリを使用する必要があります( documentation )。私はこれが最良のオプションになると思いますが、繰り返しになります-実際のパフォーマンスの問題が実際に見られる場合のみ。

16
rob

コンパクトでおそらく最も効率的:

for index, item in enumerate(your_queryset):
    ...
59
drdaeman

他のすべてのオブジェクトの中でオブジェクトがどこにあるかを知りたいだけの場合(たとえば、ランクを決定するとき)、次の前にオブジェクトを数えることで迅速に行うことができます。

    index = MyModel.objects.filter(sortField__lt = myObject.sortField).count()
34
Richard

説明の目的で、モデルが主キーidを備えた標準であると仮定して、評価します

list(qs.values_list('id', flat=True)).index(obj.id)

objqsのインデックスを検索します。 listを使用するとクエリセットが評価されますが、元のクエリセットではなく派生クエリセットが評価されます。この評価では、SQLクエリを実行してidフィールドのみを取得し、他のフィールドをフェッチする時間を無駄にしません。

13
Vinay Sajip

queryset.extra(…) といくつかの生のSQLを使用してこれを行うことができます:

queryset = queryset.order_by("id")
record500 = queryset[500]

numbered_qs = queryset.extra(select={
    'queryset_row_number': 'ROW_NUMBER() OVER (ORDER BY "id")'
})

from Django.db import connection
cursor = connection.cursor()
cursor.execute(
    "WITH OrderedQueryset AS (" + str(numbered_qs.query) + ") "
    "SELECT queryset_row_number FROM OrderedQueryset WHERE id = %s",
    [record500.id]
    )
index = cursor.fetchall()[0][0]

index == 501 # because row_number() is 1 indexed not 0 indexed
2
Jiaaro

単純なPythonの方法で、クエリセット内の要素のインデックスをクエリすることが可能です。

(*qs,).index(instance)

この答えは、クエリセットをリストにアンパックし、組み込みのPythonインデックス関数を使用して、その位置を決定します。

2
Peter Brooks