2016-12-01 3 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

업데이트 문은 단일 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