Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/291.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Django中的游标是否在打开的事务中运行?_Python_Sql_Django_Postgresql_Python Db Api - Fatal编程技术网

Python Django中的游标是否在打开的事务中运行?

Python Django中的游标是否在打开的事务中运行?,python,sql,django,postgresql,python-db-api,Python,Sql,Django,Postgresql,Python Db Api,我的Django应用程序正在使用一些自定义SQL,我正在这样的视图中执行这些SQL: db = router.db_for_write(model) cursor = connections[db].cursor() cursor.execute("INSERT INTO ....") 由于我使用的是TransactionMiddleware,因此我的视图在事务内部运行,但我不清楚获得这样的新游标是“转义”当前打开的事务,还是游标仍然是打开的事务的一部分。我收到一些错误消息,使我相信游标正在事

我的Django应用程序正在使用一些自定义SQL,我正在这样的视图中执行这些SQL:

db = router.db_for_write(model)
cursor = connections[db].cursor()
cursor.execute("INSERT INTO ....")
由于我使用的是
TransactionMiddleware
,因此我的视图在事务内部运行,但我不清楚获得这样的新游标是“转义”当前打开的事务,还是游标仍然是打开的事务的一部分。我收到一些错误消息,使我相信游标正在事务内部运行

我希望能够使用游标在由
TransactionMiddleware
打开的事务之外执行SQL命令。这可能吗


如果重要的话,我正在用PostgreSQL 8.4数据库运行Django 1.4。

如果有一个视图需要手动管理事务,那么应该在该视图中使用decorator手动提交


是的,导入事务游标只提供事务的游标,而不创建新事务。

我相信您需要一个单独的db连接来获得一个单独的、同时进行的事务。我也非常确定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的回答有什么问题?您可以随时提交/回滚,因此没有任何东西可以阻止您在单个视图中的不同事务中执行不同的任务。这些事务必须是并行的,而不是连续的,这一事实暗示了它们之间存在某种逻辑联系,在我看来,这表明它们实际上应该在同一个事务中

如果另一方面,你只是试图模拟某种脱机处理,其成功或失败与视图并不特别相关,请考虑设置消息队列并在单独的进程中执行这些插入。这是一个很受欢迎的软件包。然而,如果响应时间不是一个主要问题,我仍然认为连续的事务应该足够了

更新: 如果您希望数据库支持的缓存在自动提交模式下运行,同时仍在单个(单独)事务中运行业务逻辑,那么有一种django方法。您需要做的就是确保缓存发生在
commit\u on\u success
之外:

  • 如果您只是在使用缓存中间件,请确保它位于
    TransactionMiddleware
    之外

  • 如果您使用缓存视图装饰器,我大胆猜测您可以禁用
    TransactionMiddleware
    (或者将问题视图放在
    自动提交
    装饰器中),并在缓存装饰器中使用
    提交成功
    装饰器。这看起来很有趣,但我不知道为什么不起作用:

    @transaction.autocommit
    @cache_page(500)
    @transaction.commit_on_success
    def my_view(request):
        "..."
    
  • 如果使用模板缓存或执行更复杂的手动缓存,还可以禁用
    TransactionMiddleware
    (或将问题视图放在
    自动提交
    装饰器中),并使用
    提交成功
    作为上下文管理器,只在托管事务中放置所需的代码,将视图的其余部分保留在自动提交中

    @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)
    

谢谢。我想做的是继续在事务中运行视图,但也要打开到数据库的单独连接,以便在视图事务之外执行SQL。这可能吗?如果我用@transaction.commit\u手动或自动提交在视图中修饰一个函数,这会起作用吗?问题似乎是你是否可以打开一个不在当前事务中的连接。您的答案是您可以对当前事务执行的操作。感谢您的帮助。在浏览了Django源代码之后,我得出了相同的结论,即需要创建另一个数据库连接。我正在将Django缓存与数据库后端一起使用,并试图找出一个间歇性问题,我认为这是由不同事务同时更新缓存引起的。因为缓存不需要在事务中保持一致,所以我想将缓存事务移动到自动提交。我仍然不确定我是否完全理解这有什么帮助,这使我认为这仍然不是您真正想要的,但我已经用更简单的方法更新了我的答案,使缓存查询不进入业务逻辑事务。
@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)