首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >用non_atomic_requests替换django装饰器commit_manually

用non_atomic_requests替换django装饰器commit_manually
EN

Stack Overflow用户
提问于 2019-06-06 05:33:41
回答 1查看 298关注 0票数 2

我有一个导入Excel文件的Django视图,如果发生异常,我希望捕获它们并报告它们,并回滚任何保存。尽管我使用了non_atomic_requests装饰器,但我还是得到了一个TransactionManagementError。

  1. ,因为我也在使用login_required装饰器,所以我想它们可能会互相干扰。首先,我颠倒了顺序,然后删除了所需的登录。没有变化。
  2. 我已经尝试全局禁用自动事务了。也许我没有做对,但这不是我想要的解决方案。
  3. 我删除了有问题的代码行(见下文),但当我试图回滚

时,同样的错误也发生了

它运行在带有最新Django的Python3.7.3上,并使用SQLlite。我现在将其作为单元测试运行,尽管我可能滥用了这个术语。可以说它是作为Django TestCase运行的。

代码语言:javascript
复制
@transaction.non_atomic_requests
@login_required(login_url='/accounts/login/?next=/finance/gl_upload/')
def gl_upload(request):
    transaction.set_autocommit(False)
    if upriv(request.user, ['admin', 'finance']) == 'admin':
        if request.method == 'POST':

... file processing here ...

                except Exception as e:
                    errs.append(format('Exception "{1}" at row {0}\n'.format(p['rownum'], e)))
                if errs:
                    transaction.rollback()
                    rows_deleted = 0
                    rows_inserted = 0
                    print(''.join('Error: {0}\n'.format(e) for e in errs))
                else:
                    transaction.commit()
                    rows_deleted = Gldata.objects.filter(item='Actual', period_gte=older, period_lte=newest).delete()
                    rows_inserted = Gldata.objects.filter(item=temp_item).update(item='Actual')
                transaction.set_autocommit(True)
                print('Deleted: {0}, inserted: {1}'.format(rows_delete, rows_inserted))
                return render(request, 'gl_upload.html', {'inserted': rows_inserted, 'removed': rows_deleted, 'errors': errs})
            else:
                return render(request, 'gl_upload.html', {'form': form})
        else:
            form = uploadForm()
            return render(request, 'gl_upload.html', {'form': form})

我在set_autocommit上收到一个TransactionManagementError,表明一个原子块是活动的,即使我知道装饰器会禁用它。几年前,我使用了旧的commit_manually装饰器,它工作得很好。

文件"C:\Users\csullivan\responsive\finance\views.py",第25行,在gl_upload transaction.set_autocommit(False)文件“C:\Users\csullivan\responsive\finance\views.py”,行30中,在gl_upload return get_connection(using).set_autocommit(autocommit)文件"C:\Users\csullivan\responsive\env\lib\site-packages\django\db\backends\base\base.py",行394中,在set_autocommit self.validate_no_atomic_block()文件"C:\Users\csullivan\responsive\env\lib\site-packages\django\db\backends\base\base.py",行433中,在validate_no_atomic_block中,“当‘原子’块处于活动状态时,这是被禁止的。”)django.db.transaction.TransactionManagementError:当‘原子’块处于活动状态时,这是被禁止的。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-06-06 05:50:17

我认为atomic()装饰器/上下文管理器提供了您所需要的东西--如果底层代码成功,它将提交事务,当出现异常时,它将回滚。

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

代码语言:javascript
复制
with atomic():
  process_xls_files()

您不应该需要手动调用transaction.set_autocommit()和类似的低级方法,除非您有非常特定的需求,并且“常规”事务处理是不够的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56468315

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档