Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/365.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 decorator commit_手动替换为非_原子_请求_Python_Django_Django Views - Fatal编程技术网

Python 将django decorator commit_手动替换为非_原子_请求

Python 将django decorator commit_手动替换为非_原子_请求,python,django,django-views,Python,Django,Django Views,我有一个Django视图,它导入一个Excel文件,如果出现异常,我希望捕获它们并报告它们,并回滚任何保存。我得到了一个TransactionManagementError,即使我使用了非原子请求装饰器 由于我也在使用登录所需的装饰程序,我想他们可能会相互干扰。首先我颠倒了顺序,然后删除了所需的登录名。没有变化 我尝试在全球范围内禁用自动事务。也许我做得不对,但这不是我想要的解决方案 我删除了有问题的代码行(见下文),但在尝试回滚时发生了相同的错误 它使用最新的Django和SQLlite在Py

我有一个Django视图,它导入一个Excel文件,如果出现异常,我希望捕获它们并报告它们,并回滚任何保存。我得到了一个TransactionManagementError,即使我使用了非原子请求装饰器

  • 由于我也在使用登录所需的装饰程序,我想他们可能会相互干扰。首先我颠倒了顺序,然后删除了所需的登录名。没有变化

  • 我尝试在全球范围内禁用自动事务。也许我做得不对,但这不是我想要的解决方案

  • 我删除了有问题的代码行(见下文),但在尝试回滚时发生了相同的错误

  • 它使用最新的Django和SQLlite在Python3.7.3上运行。我现在把它作为一个单元测试来运行,尽管我可能滥用了这个术语。只需说它是作为Django测试用例运行的

    @transaction.non_原子请求
    @需要登录(登录url='/accounts/login/?next=/finance/gl\u upload/)
    def gl_上传(请求):
    事务。设置自动提交(错误)
    如果upriv(request.user,['admin','finance'])=='admin':
    如果request.method==“POST”:
    ... 文件处理在这里。。。
    例外情况除外,如e:
    errs.append(格式({0}\n'行的异常“{1}”)。格式(p['rownum'],e)))
    如果出现错误:
    事务。回滚()
    行\u已删除=0
    插入的行数=0
    打印(“”.join('Error:{0}\n'。errs中e的格式(e))
    其他:
    commit()事务
    行\u deleted=Gldata.objects.filter(item='Actual',period\u gte=older,period\u lte=newest).delete()
    行\u inserted=Gldata.objects.filter(item=temp\u item.update(item='Actual'))
    事务。设置自动提交(True)
    打印('Deleted:{0},inserted:{1}'。格式(rows\u delete,rows\u inserted))
    返回呈现(请求,'gl_upload.html',{'inserted':行插入,'removed':行删除,'errors':errs})
    其他:
    返回呈现(请求'gl_upload.html',{'form':form})
    其他:
    form=uploadForm()
    返回呈现(请求'gl_upload.html',{'form':form})
    
    我在set_autocommit上收到一个TransactionManagementError,指示一个原子块处于活动状态,尽管我知道装饰程序会禁用它。几年前,我使用了旧的commit_手动装饰器,效果很好

    文件“C:\Users\csullivan\responsive\finance\views.py”,第25行,gl\U上传 事务。设置自动提交(错误) 文件“C:\Users\csullivan\responsive\env\lib\site packages\django\db\transaction.py”,第30行,在set\u autocommit中 返回获取连接(使用)。设置自动提交(自动提交) 文件“C:\Users\csullivan\responsive\env\lib\site packages\django\db\backends\base\base.py”,第394行,在set\u autocommit中 self.validate\u no\u原子块() 文件“C:\Users\csullivan\responsive\env\lib\site packages\django\db\backends\base\base.py”,第433行,在validate\u no\u atomic\u块中 “当“原子”块处于活动状态时,这是禁止的。”) django.db.transaction.TransactionManagementError:当“原子”块处于活动状态时,这是禁止的。

    我认为 decorator/contextmanager提供了您所需要的内容 --如果底层代码成功并回滚,它将提交事务 当出现异常时

    所以在你的情况下,我会:

    with atomic():
      process_xls_files()
    
    您不需要手动调用
    transaction.set_autocommit()
    和类似的低级方法,
    除非您有非常特殊的需求,而且“正常”的事务处理是不够的。

    谢谢Tomasz。原子是视图的默认设置,不是吗?我希望视图读取整个文件并跟踪它发现的错误(如果有)。如果没有错误,那么我想提交插入,如果有错误,我想回滚并在响应中包括错误列表。我不想将整个文件读入内存,然后进行一次大批量创建,这是另一种方法。由于此文件有50K行,而另一个类似的练习将有120K行。@除非使用
    ATOMIC\u REQUESTS=True
    设置,否则默认为Deepstop Autocommit。根据您所说的,使用atomic()的
    方法将完全满足您的需要--DB事务将“累积”所有
    插入的
    数据,如果没有错误,则在原子块退出时将提交这些数据。如果出现错误,整个事务都将回滚。顺便说一句,即使您设置了
    ATOMIC\u REQUESTS=True
    ATOMIC()(主要区别在于,提交的保存点仍然可以回滚,例如,当整个事务回滚时)。这有点复杂,但它可以工作。整个处理循环在with块中,在循环结束时,如果填充了错误列表,我只会引发一个通用异常,并在with块外捕获它。虽然我不得不说我更喜欢显式提交和回滚,但感谢您为我指出了一个可行的解决方案!@Deepstop我是gla我想说,与
    atomic()
    的“魔力”相比,手动管理事务要复杂得多
    是因为它总是做正确的事情,因此很难意外地引入错误。而手动方式很容易出错,因为您需要覆盖每个可能的场景。此外,多个嵌套的
    原子()
    块正确交互,最外层处理事务,内部处理保存点(s) 。