我相信你需要一个单独的数据库连接来获得一个单独的、同时的事务。我也很确定 django 每个数据库只管理一个连接。但是你可以创建另一个。可能有一些很好的理由不这样做。复杂性浮现在脑海中。
我认为这样的事情会起作用:
from django.conf import settings
from django.db.utils import ConnectionHandler
def my_view(request):
"""Flirt with complexity by using two connections to db"""
private_connections = ConnectionHandler(settings.DATABASES)
db = router.db_for_write(model)
new_conn = private_connections[db]
new_conn.enter_transaction_management()
new_conn.managed(True)
new_cur = new_conn.cursor()
new_cur.execute("INSERT INTO ...")
new_conn.commit()
new_conn.close()
请注意,您不能使用django.db.transaction
它,因为它在 中的全局连接实例上运行django.db.connections
,但无论如何,这只是连接对象上事务管理方法的一个薄包装器。
我想真正的问题是你为什么要这样做?! Lakshman Prasad 的回答有什么问题?您可以随时提交/回滚,因此没有什么可以阻止您在单个视图中的不同事务中执行不同的任务。事务必须是并行的而不是连续的这一事实暗示了它们之间的某种逻辑联系,在我看来,这表明它们确实应该在同一个事务中。
另一方面,如果您只是试图模拟某种离线处理,其成功或失败根本与视图无关,请考虑设置消息队列并在单独的过程。 Celery是一个很受欢迎的包。但是,如果响应时间不是主要问题,我仍然认为连续事务就足够了。
更新:
如果您希望数据库支持的缓存在自动提交模式下运行,同时仍然在单个(单独的)事务中运行业务逻辑,那么有一种 django 方式。您需要做的就是确保缓存发生在commit_on_success
:
如果您只是使用缓存中间件,请确保它位于TransactionMiddleware
.
如果您使用缓存视图装饰器,我敢猜测您可以禁用TransactionMiddleware
(或将问题视图放在autocommit
装饰器中)并在缓存装饰器中使用装饰器commit_on_success
。它看起来很有趣,但我不知道为什么它不起作用:
@transaction.autocommit
@cache_page(500)
@transaction.commit_on_success
def my_view(request):
"..."
如果您使用模板缓存或进行更多涉及的手动缓存,您还可以禁用TransactionMiddleware
(或将问题视图放入autocommit
装饰器中)并commit_on_success
用作上下文管理器,仅将您需要的代码放入托管事务中,保留视图的其余部分在自动提交中。
@transaction.autocommit
def my_view(request):
data = cache.get(some_key)
with transaction.commit_on_success():
context = do_some_processing(data)
cache.set(some_key, context['data'])
return render('template/with/cache/blocks.html', context=context)