【问题标题】:Atomic transactions in Django app in a for loopfor循环中的Django应用程序中的原子事务
【发布时间】:2019-07-26 08:01:31
【问题描述】:

在我的 django 应用程序中,我有一个处理用户上传的 XLS 文件的 celery 任务。 它被用于执行诸如“大量导入”数据之类的操作。

在 for 循环中,我正在处理每一行 - 从每一行我想创建一个模型实例对象(所以我将有多个 Model.objects.create(...) 调用 - 对于一行,我可能会创建多个对象及其外键)。

在 django 中是否有可能对整个 for 循环进行原子事务? 例如,如果 XLS 包含 100 行——其中 90 行成功,但 91 行不成功(因为行中的数据错误)——是否可以回滚之前的 90 次(或更多)数据库保存?

我的代码如下:

workbook = xlrd.open_workbook(importobject.file.path)
worksheet = workbook.sheet_by_index(0)

processed_rows = []
omitted_rows = []

print('Mass import rows: ', worksheet.nrows)

startrange = 0

if str(worksheet.cell(0, 0).value) == 'header':
    print('Omit first row as header row')
    startrange = 1

for rowno in range(startrange, worksheet.nrows):
    logger.info('Processing row {}:'.format(rowno))

    for colno in range(worksheet.ncols):
        cell = worksheet.cell(rowno, colno)
        print('Row {}, Col {}:'.format(rowno, colno), str(cell.value))
        # process call and row
    # validate and save object here - if not valid - rollback whole mass import
    #MyModel.objects.create()

【问题讨论】:

    标签: python django postgresql django-orm


    【解决方案1】:

    正如交易文档所述,您可以control them explicitly。在你的情况下,你可以用上下文管理器包装它:

    from django.db import transaction
    
    with transaction.atomic():
        for rowno in range(startrange, worksheet.nrows):
            logger.info('Processing row {}:'.format(rowno))
    
            for colno in range(worksheet.ncols):
                cell = worksheet.cell(rowno, colno)
                print('Row {}, Col {}:'.format(rowno, colno), str(cell.value))
            if not ... valid:
                raise IntegrityError()  # will cause the entire transaction to be rolled back
    

    【讨论】:

    • 如果不想引发异常,也可以使用transaction.set_rollback(True)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-06
    • 1970-01-01
    • 2012-10-28
    • 1970-01-01
    相关资源
    最近更新 更多