python - 导入文件时在 Django 中使用事务

标签 python django

我正在构建一个 Django 应用程序,用户将在其中导入 Excel/CSV 文件。每行都通过一个表格提供,如解释的那样 here (底部的示例 3)。

对于我的导入器,我首先遍历整个文件,然后在表格中显示所有错误。如果没有错误,我会显示将要导入的内容的摘要。然后用户可以确认,文件将被导入。问题是,行相互依赖以进行验证(唯一性约束等),因此我必须将每一行保存到数据库中才能进行验证。

我想出了下面的方法,但我以前没有使用过原子事务,我担心潜在的陷阱。我最多可以导入 10000 行。

下面的代码是否适合我想要实现的目标,或者是否有更好的方法?

def import_from_csv(filename, preview):
    sid = transaction.savepoint()
    result = import_data(filename)
    if result.has_error or preview:
        transaction.savepoint_rollback(sid)
    else:
        transaction.savepoint_commit(sid)
    return result

附加信息:

在我的应用程序中有两个不同的 View 。第一个 View 是预览 View 。在这种情况下,我调用 import_from_csv 并将预览设置为 True。这样,插入将始终回滚。它返回本应导入的结果。如果没有错误,我将文件的位置保存在 session 变量中。如果用户点击确认,我再次调用 import_from_csv,但这次预览为 False。由于我在预览步骤已经检查了文件,所以应该不会有任何错误,结果会被提交。我知道这可以优化,因为我处理文件两次。

我正在使用 Django 1.9 和 Postgres(在 Heroku 上)

最佳答案

陷阱 1

无论数据库是什么,插入 10,000 行都不会很快。您可能只能在超时之前将其挤入,但您是在冒险。

陷阱 2

在事务中,一旦发生错误,事务就不能用于进一步的插入,直到你回滚。如果 CSV 中的第二行导致错误,您会发现实际上没有插入任何内容。

根据您更新的信息:

您仍然很难弄清楚哪些记录可以插入,哪些不可以。您可能需要 import_data 中的auto commit,这会进一步降低速度。

陷阱 3

该方法实际上并没有为用户提供确认或拒绝插入的机会。用户操作将由单独的 HTTP 请求处理。它将不同于发送 CSV 数据的那个。因此,当收到用户操作时,此事务已完成并已清理,无法回滚。

陷阱 4

如果前面的行依赖于后面的行(你说行之间可能有关系)插入将失败。

解决方案

使用数据库批量加载来填充与真实事物相同的临时表除了限制。您尚未指定您的数据库是什么。例如,在 postgresql 中批量加载的方式是 COPY FROM在 mysql 中它是 LOAD DATA .

加载数据后,将约束添加到临时表。与原始表进行连接以确定哪些行是重复的。询问用户是忽略还是更新重复项。然后执行 INSERT SELECT

对提供的额外信息的回应:

如果您使用的是 celery 任务,您可能不依赖于 COPY,但最好将初始导入到临时表中。这样就避免了两次处理数据的需要。而且很容易找出 CSV 文件中的哪些行导致重复。

关于python - 导入文件时在 Django 中使用事务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36947495/

相关文章:

python - django.template.exceptions.TemplateSyntaxError : Could not parse some characters: |{{b.count}}||rangef

python - 为什么我在构建 docker 镜像时遇到这个错误?

python - 如何在 Django 单元测试中获取请求对象?

python - 如何在循环期间更新 Django 查询集中的数据?

python - 查看不工作/如何在 shell 中测试它?

python - Argparse"ArgumentError : argument -h/--help: conflicting option string(s): -h, --help"

python - 为什么 asyncio 中的异常迟到或根本不出现?

Python Click - 从配置文件提供参数和选项

python - 我如何做大于/小于使用 MongoDB?

python - Django 多个 unique_together 是否在 PostgreSQL 中被错误映射?