2

this_fieldとして保存されるフィールド(それを呼びましょう)を持つモデルがありますstring。の値はthis_field次の形式ですChar###-のように、次のような値があります:A4またはA34またはA55(常に同じ最初の文字を持つことに注意してください)。

すべてのレコードを選択して、このフィールドで並べ替える方法はありますか?現在、私が行うとき、私.order_by('this_field')は次のような注文を受け取ります:

A1 A13 A2 A25 等...

私が欲しいのは:

A1 A2 A13 A25 等...

このクエリセットを適切に順序付けて実現するための最善のアプローチ方法またはソリューションはありますか?

4

3 に答える 3

3

クエリセットの順序付けは、Django ではなく、データベース バックエンドによって処理されます。これにより、注文方法を変更するオプションが制限されます。すべてのデータをロードして Python で並べ替えるか、クエリに追加オプションを追加して、関数を定義することでデータベースに何らかのカスタム並べ替えを使用させることができます。

queryset extra()関数を使用すると、並べ替えのためにカスタム SQL を実行することで、必要なことを行うことができますが、移植性が低下します。

あなたの例では、入力フィールドを最初の文字と残りの整数値の 2 つのデータ セットに分割するだけで十分でしょう。次に、両方の列に並べ替えを適用できます。以下に例を示します (未テスト)。

qs = MyModel.objects.all()

# Add in a couple of extra SELECT columns, pulling apart this_field into
# this_field_a (the character portion) and this_field_b (the integer portion).

qs = qs.extra(select={
              'this_field_a': "SUBSTR(this_field, 1)",
              'this_field_b': "CAST(substr(this_field, 2) AS UNSIGNED)"})

このextra呼び出しにより、2 つの新しいフィールドが呼び出しに追加されSELECTます。最初の句はフィールドの最初の文字を取り出し、2 番目の句はフィールドの残りを整数に変換します。

order_byこれらのフィールドでできるようになりました。に 2 つのフィールドを指定するとorder_by、順序付けは最初に文字フィールドに適用され、次に整数フィールドに適用されます。

例えば

qs = qs.order_by('this_field_a', 'this_field_b')

この例は、MySql と SQLite の両方で機能するはずです。ソートにのみ使用される単一の追加フィールドを作成して、order_by()呼び出しで単一のフィールドのみを指定できるようにすることもできます。

于 2013-03-18T01:07:25.137 に答える
2

この並べ替え順序を頻繁に使用し、大きなテーブルで使用する場合は、値が分離された 2 つのフィールドについて考える必要があります。

  1. テキストまたは文字フィールドでは、アルファ値は小文字のみにする必要がありますdb_index=True
  2. 数値は、db_index=True設定された整数フィールドにある必要があります。

qs.order_by('alpha_sort_field', 'numeric_sort_field')

そうしないと、パフォーマンスにいくらか (または最大で) 影響を与える可能性があります。

于 2016-01-18T15:26:38.863 に答える
1

別の方法として、 の int 部分に基づいて QuerySet をソートしますthis_field

qs = ModelClass.objects.all()
sorted_qs = sorted(qs, key=lambda ModelClass: int(ModelClass.this_field[1:]))
于 2013-03-18T01:45:50.270 に答える