2016-12-01 6 views
1

クエリセットのフィールドをアトミ​​ックに更新しようとしています。私はこのようなものがあります:クエリセット内のすべてのインスタンスをアトミックにカウントする

counter = 0 
for row in myQuerySet: 
    row.myField = counter 
    counter = counter + 1 
    row.save() 

動作しますが、私は、レジスタの数百を持っているので、私は、アトミックこれをしたいと、それは時間の無駄です。私はこのようなものが必要です:

counter = 0 
myQuerySet.update(myField=(counter+=1)) 

しかし、これは動作しません。これに対して正しいsintaxは何ですか?動作しますが、私はアトミックこれをしたい

+1

updateステートメントは単一のSQLクエリを作成します。テーブルの一部ではない値を使用している場合(つまり、フィールドではない場合)、定数として扱われます。その場合、すべての行は同じ値。 – AKS

+1

'F()'オブジェクトは、既存のフィールド値に基づいてフィールドを更新するのに役立ちますが、増分する外部値に基づいてフィールドを更新する方法は考えられません。 –

+0

@ Sayse "step_number"整数フィールドを持つレジスタがたくさんあります。このフィールドは手動で変更できます。たとえば、5つのレジスタがある場合、step_numbersは1,2,3,8,9になります。たとえば、ギャップのある増分シーケンスを取得できます。しかし、私は1,2,3,4,5シーケンスを得るために番号を付けなおしたいと思います。それがカウンターの目的です。 – MouTio

答えて

2

は、[...]

多くの場合、答えはQuerySet.update methodを使用することです。これは、クエリーセット内のすべてのインスタンスに対して、同じこと(動的に変更する必要のないもの)を実行したいときに機能します。

実行する操作では、各インスタンスに順番に動的な変更が必要なように見えるので、代わりにselect_for_update methodを使用できます。

from django.db import transaction 

dolors = LoremIpsum.objects.select_for_update().filter(dolor=True) 

with transaction.atomic(): 
    counter = 0 
    for lorem_ipsum in dolors: 
     lorem_ipsum.amet = counter 
     counter += 1 
     lorem_ipsum.save() 

documentation for select_for_updateが、これは何をしたいん言う:

一致したすべてのエントリは、他のトランザクションがそれらのロックを変更したり、取得することが防止されることを意味し、トランザクションブロックの終わりまでロックされます。

クエリセットはアイテムは、「トランザクションブロックの終わりまでロック」されますので、あなたは、上記のようtransaction.atomicを使用してトランザクションブロック内で、あなたの操作を実行する必要があります。

+1

それだけです! select_for_updateの前に "objects"部分がないので、select_for_updateをトランザクション外で使用することはできないため、 "with transaction.atomic()"(django.dbインポートトランザクション)を追加するために必要なものだけを追加します。 – MouTio

関連する問題