2011-01-11 23 views
1

注文書でテーブル内のアイテムを選択したい場合は、 SQLを使用します。注文を指定しないと、昇順の主キーが使用され、 'IN'の順序が失われます。 1は「IN」と秩序維持するために、このSQL要求を使用できるように 私が読ん:今すぐDjangoでINを同じ順序で選択しますか?

SELECT * FROM table WHERE id IN (118,17,113,23,72) ORDER BY FIELD(id,118,17,113,23,72) 

を、どのように私はジャンゴの中に、この要求をコーディングすることができますか? 注:SQLにジョブを実行させたいので、.in_bulk()クエリーセットメソッドを使用したくありません。

答えて

2

あなたはジャンゴ1.2+でraw()マネージャのメソッドを使用してこれを行うことができます。

ids = "118,17,113,23,72" 
results = MyModel.objects.raw('SELECT * FROM myapp_mymodel WHERE `id` IN (%s) ' 
           'ORDER BY FIELD (id, %s)' % (ids, ids)) 

いくつかの注意事項:

  • あなたは要素BY ORDERのためのパラメータ処理を使用することはできませんので、これは、SQLインジェクション攻撃に対して潜在的に脆弱です。 idsリストのサニタイズを必ず行ってください。

  • raw()通常のクエリセットのようにクエリをキャッシュしません。クエリを繰り返すたびにクエリを再評価します。値が複数回必要な場合は、最初にlist()に電話してください。

  • ORDER BY FIELD MySQL固有の拡張機能です。

  • はまた、最終的な要求は意味がありませんのでご注意:in_bulk()は仕事をするためにSQLを使用して行います。しかし、それはあなたの質問には適していません。

+0

IN_bulk()はIN SQL節を使用してください。良い説明! – santiagobasulto

0

私はこれを試してみた:

とにかく
from django.db.models import Q 
# first you get the IDs 
ids = [1,2,3,4,5] 
# after that you can get a list of Q objects 
q_objects = [Q(id=id) for id in ids] 
# then you need to combine all the Q objects 
# I'll use a functional approach, an operation called fold_left but you can use a for instead 

# i need the first element 
first_q = q_objects.pop() 
final_q = reduce(lambda total,q: total | q,q_objects,first_q) 
# now you can get the result 
MyModel.objects.filter(q) 
#if you need an order simply append order_by 
MyModel.objects.filter(q).order_by(something) 

、それがIN SQL句を使用しbecouse、in_bulkによって行われるクエリを見てみましょう。これは、Djangoの1.3とMySQLを用いた試験である:あなたが唯一のdjango_toolbar使用することができます。もちろん、

SELECT [fields] 
FROM [my_table] WHERE [my_model].`id` IN (1, 2) 

python manage.py shell 


>>> from testapp.models import Car 
>>> from django.db import connection 
>>> cars = Car.objects.in_bulk([1,2]) 
>>> my_queries = connection.queries 
>>> my_queries[0]['sql'] 

これは、SQLの結果です。