我有一个用原子事务修饰的视图。但是,我总是想在这个视图中保存一个特定的操作。操作是调用第三方API,有时我需要在应用程序发出请求之前刷新令牌。但是,如果刷新后出现故障,则不会保存新令牌,而是回滚。如何始终将保存操作提交到数据库?我已经研究过使用asavepoint但我不确定我是否在正确的轨道上。
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

最佳答案

在“进程B”验证从“进程a”传递的身份验证所需的用户令牌(在进程a中的事务提交之前)出现类似问题:
为了解决这个问题,我需要“Token.objects.get_或_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'

所有令牌对象的使用现在都在“security”数据库中进行。因此,用户令牌是在独立于“默认”数据库事务的事务中创建的,它与所有django连接一样是即时的(除非您另外指定)。

关于python - 在Django原子事务中提交特定的保存操作,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31253727/

10-16 22:43