2016-12-20 11 views
3

これはF式でもっと効率的な方法でしょうか?いくつかの方法は、DBを打つのを減らすには?Django:複数のオブジェクト属性を更新する

# 1st way hits DB twice per object 
def something(): 
    pks = [4, 2, 1, 3, 0] 
    for i in range(len(pks)): 
    mymodel.objects.get(pk=pks[i]).update(attr=i) 

# 2nd way hits DB once per obj and once for the queryset 
def something(): 
    pks = [4, 2, 1, 3, 0] 
    order = Case(*[When(pk=pk, then=pos) for pos, pk in enumerate(pks)]) 
    query = mymodel.objects.filter(pk__in=pks).order_by(order) 
    for i in range(len(query)): 
    query[i].attr = i 
    query[i].save() 

変数を一貫して編集すること。

答えて

3

一般に、1つの大きなクエリではなく複数のデータベースクエリを回避する必要があります。しかし、あなたのケースは例外であるようです。 (注:私は提供された情報に基づいてこの回答をしています。質問を編集しないで、実際には....)

次のクエリは、それは主キーから単一の項目を検索しています。すべてのRDBMSはこれを本当にうまく処理するように設計されています。

mymodel.objects.get(pk=a[i]) 

Howerあなたは、このようなあなたの機能をより効率的にすることができます

def something(): 
    pks = [4, 2, 1, 3, 0] 
    for i in range(len(a)): 
    mymodel.objects.filter(pk=a[i]).update(attr=i) 

は、今では一度だけオブジェクトごとにDBに当たります。上記のクエリは、

UPDATE mapp_mymodel SET attr=i where pk=1 
+0

getとfilterの違いを説明できますか?あなたはアイテムを取得しているのにコード内にフィルタを使用しているので、getは非常に高速だと言います。複数のオブジェクトが必要な場合は、一般的にfilterを使用して、1つのオブジェクトを取得します。 –

+0

getとfilterの違いは、getがオブジェクトを取得し、見つけたときに更新を行うことです。フィルタは、実際にデータベースからスライスを取り出したり、それを反復したりするまで、データベースから何も取得しません。 – e4c5

+0

これは、DBを2回叩くと思った。なぜなら、一度オブジェクトを取得してもう一度そのオブジェクトを更新する必要があったからだ。 –

0

私は間違っていない場合は、これが動作しない、属性値、などのためのループインデックスを使用しようとしている場合を除き、あなたは

pks = [4, 2, 1, 3, 0] 
mymodel.object.filter(pk__in=pks).update(attr='test') 

ような何かを行うことができます。

+0

に翻訳されています。 pk = i、attr = i(それぞれattrが違う)なので、私はその答えを私の答えに加えたのです。上記のクエリで。 attr = 1すべてのインスタンスに対して – e4c5

+0

これは事実かもしれません(したがって、答えの最後の行)。しかしそれはちょうど入れ墨を掲示した。あなたの答えはもっと役に立ちそうです。ありがとう.. – zubhav

+0

はい私はattrの値としてインデックスを使用しています。 –

関連する問題