Django QuerySet
sで特定の順序をどのように定義しますか?
具体的には、次のようなQuerySet
がある場合:_['a10', 'a1', 'a2']
_。
通常の注文(Whatever.objects.order_by('someField')
を使用)では、_['a1', 'a10', 'a2']
_が表示されますが、探しているのは_['a1', 'a2', 'a10']
_です。
私自身の注文テクニックを定義する適切な方法は何ですか?
私の知る限り、データベース側の順序をこのように指定する方法はありません。バックエンド固有であるためです。古き良き時代のPython並べ替え:
class Foo(models.Model):
name = models.CharField(max_length=128)
Foo.objects.create(name='a10')
Foo.objects.create(name='a1')
Foo.objects.create(name='a2')
ordered = sorted(Foo.objects.all(), key=lambda n: (n[0], int(n[1:])))
print ordered # yields a1, a2, 10
この種の並べ替えが必要な場合は、順序付けを実行するモデルのカスタムmodels.Manager
サブクラスを作成することをお勧めします。何かのようなもの:
class FooManager(models.Manager):
def in_a_number_order(self, *args, **kwargs):
qs = self.get_query_set().filter(*args, **kwargs)
return sorted(qs, key=lambda n: (n[0], int(n[1:])))
class Foo(models.Model):
... as before ...
objects = FooManager()
print Foo.objects.in_a_number_order()
print Foo.objects.in_a_number_order(id__in=[5, 4, 3]) # or any filtering expression
@Jarretの答え(Pythonでソートを行う)は、単純なケースに最適です。大きなテーブルがあり、たとえば、特定の方法でソートされた結果の最初のページのみをプルしたい場合、このアプローチは失敗します(ソートを実行する前に、データベースからすべての行をプルする必要があります)。その時点で、保存時に「名前」フィールドから入力する非正規化された「ソート」フィールドを追加することを検討します。これは、通常の方法でDBレベルでソートできます。
より大きなデータセットがあり、さらにSOLRバックエンドを使用する場合(Haystackなど):
使用する solr.ICUCollationField
とともに numeric=true
ソートフィールドのタイプとしてのオプション。これは言語に従ってソートされ、数値が存在する場合は、文字列ソートではなく数値規則に従って数値部分をソートします。
参照: https://cwiki.Apache.org/confluence/display/solr/Language+Analysis#LanguageAnalysis-UnicodeCollationhttp://www.solr-start.com/javadoc/ solr-lucene/org/Apache/solr/schema/ICUCollationField.html
どこで使いたいかによります。
独自のテンプレートで使用する場合は、順序付けを行うテンプレートタグを作成することをお勧めします。その中で、使用する任意の並べ替えアルゴリズムを使用できます。
管理者では、上記のようにテンプレートを必要に応じて拡張し、テンプレートタグを読み込むことでカスタム並べ替えを行います