私はQuerySetを持っているので、それをqs
と呼びましょう。これは、この問題とは関係のない属性によって順序付けられています。次に、オブジェクトがあります。それをobj
と呼びます。ここで、obj
のqs
がefficientlyとして可能なインデックスを知りたいと思います。 Pythonから.index()
を使用したり、各オブジェクトをqs
と比較してobj
をループしたりできることはわかっていますが、何が最良かこれを実行する方法?私は高いパフォーマンスを探しており、それが私の唯一の基準です。
WindowsでPython 2.6.2をDjango 1.0.2と組み合わせて使用します。
DjangoのQuerySetsは実際にはジェネレーターであり、リストではありません(詳細については、 DjangoのQuerySetsに関するドキュメント を参照してください)。
そのため、要素のインデックスを取得するショートカットはありません。単純な反復がそれを行うための最良の方法だと思います。
手始めに、可能な限り最も簡単な方法で(反復のように)要件を実装します。あなたが本当にパフォーマンスの問題を抱えているなら、私はいくつかの異なるアプローチを使用します。
いずれの場合でも、そのようなトリックが必要であることが確実にわかっている場合は、そのようなトリックをできるだけ遅くすることをお勧めします。
更新:いくつかのSQLステートメントを直接使用して行番号を取得したい場合があります(ただし、DjangoのORMはこれをネイティブでサポートしていないため、生のSQLクエリを使用する必要があります( documentation )。私はこれが最良のオプションになると思いますが、繰り返しになります-実際のパフォーマンスの問題が実際に見られる場合のみ。
コンパクトでおそらく最も効率的:
for index, item in enumerate(your_queryset):
...
他のすべてのオブジェクトの中でオブジェクトがどこにあるかを知りたいだけの場合(たとえば、ランクを決定するとき)、次の前にオブジェクトを数えることで迅速に行うことができます。
index = MyModel.objects.filter(sortField__lt = myObject.sortField).count()
説明の目的で、モデルが主キーid
を備えた標準であると仮定して、評価します
list(qs.values_list('id', flat=True)).index(obj.id)
obj
でqs
のインデックスを検索します。 list
を使用するとクエリセットが評価されますが、元のクエリセットではなく派生クエリセットが評価されます。この評価では、SQLクエリを実行してidフィールドのみを取得し、他のフィールドをフェッチする時間を無駄にしません。
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
単純なPythonの方法で、クエリセット内の要素のインデックスをクエリすることが可能です。
(*qs,).index(instance)
この答えは、クエリセットをリストにアンパックし、組み込みのPythonインデックス関数を使用して、その位置を決定します。