Djangoの値を原子的に比較交換保存するにはどうすればModel
インスタンスField
にすることができますか? (PostgreSQLをDBバックエンドとして使用する)。Djangoのモデルフィールドを原子的に比較交換する
このようなコンテンツを持つ複数の投稿(同じフォームの送信など)は、安全でなくてもうまく動作しないクライアント側のJavaScriptまたはフォーム側の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
...
これはアトミックであることが保証されていますか?私はドキュメントでそれを見ません。そうでない場合は、私の使用例では、2つの異なる要求が「ライセンスを入金する」セクションに入ることが可能です。 – Danra
これは単一のデータベース呼び出しです。それは可能な限り原子質です。 –
@DanielRosemanは原子であるかどうか?つまり、PostgreSQLのバックエンドを想定して、このメソッドを同時に呼び出す2つの同時リクエストが、両方とも正常に値を更新することは可能ですか?それとも、最大で1つが成功することが保証されていますか? – Danra