我有一个用原子事务装饰的视图。但是,我总是希望在此视图中保存特定操作。操作是调用第三方API,有时我需要在应用程序发出请求之前刷新令牌。但是,如果在刷新之后出现故障,则新令牌不会被保存而是回滚。如何始终将保存操作提交到数据库?我已经考虑使用savepoint,但我不确定我是否在正确的轨道上。
views.py
@transaction.atomic
def my_view(request)
from another_file import fx
a = Mymodel.objects.first()
fx(a)
return a
another_file.py
def fx(obj)
from django.db import transaction
sid = transaction.savepoint()
obj.token = 'jfkds'
obj.save()
transaction.savepoint_commit(sid)
raise Exception
答案 0 :(得分:1)
遇到类似问题,过程B'过程B需要用户令牌。验证从过程A'过程中传递的身份验证在进程A中的事务已经提交之前:
要解决这个问题,我需要' Token.objects.get_or_create(user = user)'无论是否已经有一些正在进行的周边交易,都要求在自己的交易中提交。我认为您正在查看与您的问题相同的问题。
我使用单独的数据库连接进行令牌处理。因此在设置中:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'mydb',
'USER': 'mydbuser',
'PASSWORD': DBPASSWORD}}
DATABASES['security'] = DATABASES['default'] # allow independent security transactions/connections
DATABASE_ROUTERS = ['security.db_router.SecurityRouter']
路由器确保在“安全性”中处理令牌模型。数据库。您可以将路由器放在您喜欢的位置,并使用上述路由器设置将其链接。:
from rest_framework.authtoken.models import Token
class SecurityRouter(object):
def db_for_read(self, model, **hints):
return self.mine(model, **hints)
def db_for_write(self, model, **hints):
return self.mine(model, **hints)
def allow_relation(self, obj1, obj2, **hints):
return True
def allow_migrate(self, db, app_label, model=None, **hints):
return True
@staticmethod
def mine(model, **hints):
if model == Token:
return 'security'
所有Token对象的使用现在都发生在' security'数据库。因此,用户令牌是在独立于您的默认交易的交易中创建的。数据库事务,它是立即的,就像所有django连接一样(除非你另有说明)。
答案 1 :(得分:0)
或者,稍微容易一点,您可以先保存并更新令牌,然后使用with块使其余的视图操作成为原子:
# @transaction.atomic
def my_view(request)
from another_file import fx
with transaction.atomic():
# this has to be atomic to avoid write-after-read conflicts
a = Mymodel.objects.first()
fx(a)
with transaction.atomic():
# do the rest of your view operations here including another get to Mymodel.objects.first()
a = Mymodel.objects.first()
# rest of view stuff goes here
return a