2017-12-20 13 views
0

私はDjango 1.11を使用しています。私は手動でクエリセットの順序を変更する方法を見つけようとしています。ここに私のセットアップは次のとおりです。Djangoでクエリセットを手動で注文する

models.py

class Channel(models.Model): 
    channel_no = models.CharField(max_length=4, unique=True) 

    def __str__(self): 
     return self.channel_no 

私は私が私のために使用したいチャンネル番号の配列を持っている:

私がオーダーすることを使用するにはどうすればよい
channel_order = ['2','4','6','8','10','1','3','5','7','9'] 

クエリーセット?

私はMySQLでこれを実現するには、フィールドをSelectステートメントに使用してください。ここに例があります:

SELECT * FROM Channel 
ORDER BY FIELD(`channel_no`,'2','4','6','8','10','1','3','5','7','9') 
+0

は、通常、あなたが '.order_by(「channel_noを」)'を使用することができますが、これは辞書的にご注文されます:あなたは、ユーザーによって定義されたカスタムの順序付けを必要と

UPDATEは

これは、あなたがそれを達成することができる方法でありますCharFieldのために。 CharFieldを使用してIntegerFieldではなく数値を格納する理由はありますか? – Tim

+0

これを見ていただきありがとうございます。私はIntegerFieldにすることができますが、アプリケーションは、データベースに単一の文字列として入力することで、使用したいチャンネルの順序を入力する設定です。 – RMP

+0

注文のために文字列を明示的に許可している場合、おそらく必要なのは語彙の順序です。クエリーセットに '.order_by( 'channel_no')'を追加するだけです。 – Tim

答えて

0

あなたの注文が奇妙なchannel_noであっても、私はあなたに次の解決策があります。

from django.db.models import Func, F, IntegerField 

qs = Channel.objects.annotate(
    channel_no_as_int=Cast(F('channel_no'), IntegerField()), 
    ordering=Func(F('channel_no_as_int'), 2, function='Mod') * 5000 + F(
     'channel_no_as_int')).order_by('ordering') 

あなたはMAX_LENGTH = 4を持っているとして、その後最大channel_noは私が奇数(MOD(番号をシフト乗数= 5000を取ったので、そこでも最大5000となると5000奇数可能性があることを意味している9999に等しい、2) == 1)。

order = '2', '4', '6', '8', '10', '1', '3', '5', '7', '9' 
order = map(Value, order) 
qs = Channel.objects.annotate(
    ordering=Func('channel_no', *order, function='FIELD')).order_by('ordering') 
関連する問題