2016-10-31 7 views
1

장고의 값을 원자 적으로 비교 교환 저장하려면 Model 인스턴스 Field을 어떻게 사용할 수 있습니까? (PostgreSQL을 DB 백엔드로 사용).장고의 모델 필드를 원자 적으로 비교 교환하기

예를 들어 유사한 콘텐츠 (예 : 같은 양식의 제출)가있는 여러 게시물이 안전하지 않고 때로는 작동하는 클라이언트 측 자바 스크립트 또는 양식 UUID의 서버 측 추적에만 의존하지 않고 한 번만 적용되도록하는 경우가 있습니다 이는 악성 다중 게시물로부터 안전하지 못합니다.

예를 들어

:

def compare_exchange_save(model_object, field_name, comp, exch): 
    # How to implement? 
    .... 


from django.views.generic.edit import FormView  
from django.db import transaction 
from my_app.models import LicenseCode 

class LicenseCodeFormView(FormView): 
    def post(self, request, ...): 

     # Get object matching code entered in form 
     license_code = LicenseCode.objects.get(...) 

     # Safely redeem the code exactly once 
     # No change is made in case of error 
     try: 
      with transaction.atomic() 
       if compare_exchange_save(license_code, 'was_redeemed', False, True): 
        # Deposit a license for the user with a 3rd party service. Raises an exception if it fails. 
        ... 
       else: 
        # License code already redeemed, don't deposit another license. 
        pass 
     except: 
      # Handle exception 
      ... 

답변

1

은 무엇 당신이 찾고있는 것은 검색어 세트 개체에 update 기능입니다. 케이스/1.8에서 온 - 링크 1.10입니다 conditional updates참고에 문서를 체크 아웃 - 객체가되면

이 값에 따라 케이스와 비교를 할 수 있습니다.

필드의 값을 참조하는 데 사용되는 F을 사용하는 유틸리티를 찾을 수도 있습니다. 그냥 등호의 오른쪽에 그것을 참조, F 객체를 사용해야하는 경우

(Model.objects 
.filter(id=my_id) 
.update(field_to_be_updated=Case(
     When(my_field=True, then=Value(get_new_license_string()), 
     default=Value(''), 
     output_field=models.CharField()))) 

을 : 내 모델 모델의 값을 업데이트해야

: 예를 들어

갱신 표현식.

업데이트는 transaction.atomic() 문맥 관리자의 사용을 필요로하지는 않지만 다른 데이터베이스 작업을 수행해야하는 경우에 그 코드를 포장하기 위해 계속해야 transaction.atomic()

편집 :

것은 또한하실 수 있습니다 쿼리 세트가 실행될 때 행 잠금을 구현하는 쿼리 세트 select_for_update 메서드를 사용하십시오 docs.

+0

원자 단위로 보장 되나요? 나는 문서에서 그것을 보지 못한다. 그렇지 않은 경우, 나의 사용 사례에서 두 개의 다른 요청이 "라이센스 예치"섹션에 입력하는 것이 가능합니다. – Danra

+0

이것은 단일 데이터베이스 호출입니다. 가능한 한 원자 적입니다. –

+0

@DanielRoseman은 원자이거나 그렇지 않은가요? 즉, PostgreSQL 백엔드를 가정하면 동시에이 메소드를 호출하는 두 개의 동시 요청이 모두 성공적으로 값을 업데이트 할 수 있습니까? 아니면 대부분이 성공할 것이라고 보장합니까? – Danra