使用Python-Django将CSV文件导入PostgreSQL数据库

7 投票
4 回答
5636 浏览
提问于 2025-04-17 19:28

注意:请向下滚动到背景部分,获取有用的细节。假设这个项目使用的是Python-Django和South,以下是相关的说明。

将以下CSV导入的最佳方法是什么

"john","doe","savings","personal"
"john","doe","savings","business"
"john","doe","checking","personal"
"john","doe","checking","business"
"jemma","donut","checking","personal"

到一个PostgreSQL数据库中,相关的表有PersonAccountAccountType,需要考虑:

  1. 管理员用户可以通过自定义界面实时更改数据库模型和CSV导入的表示方式
  2. 保存的CSV到数据库的表/字段映射在普通用户导入CSV文件时会被使用

到目前为止,考虑了两种方法

  1. ETL-API方法:提供一个ETL API,输入一个电子表格、我的CSV到数据库的表/字段映射和目标数据库的连接信息。然后,API会加载电子表格并填充目标数据库的表。根据pygrametl的情况,我觉得我想要的可能实现不了。实际上,我不确定是否有任何ETL API可以做到这一点。
  2. 逐行插入方法:解析CSV到数据库的表/字段映射,解析电子表格,并生成“连接顺序”的SQL插入语句。

我实现了第二种方法,但在算法缺陷和代码复杂性上遇到了困难。有没有可以满足我需求的Python ETL API?或者有没有不需要重新发明轮子的其他方法?


背景

我工作的公司希望将数百个特定项目的设计电子表格从SharePoint迁移到数据库中。我们快完成一个网络应用程序,它可以让管理员为每个项目定义/建模一个数据库,存储电子表格,并定义浏览体验。在这个完成阶段,转向商业工具不是一个选项。可以把这个网络应用程序想象成一个django-admin的替代品,虽然它并不是,具有数据库建模界面、CSV导入/导出功能、可定制的浏览和模块化的代码,以满足项目特定的定制需求。

目前实现的CSV导入界面比较繁琐且存在bug,所以我在尝试获取反馈并寻找其他方法。

4 个回答

0

我每个月几乎都要在工作中写导入子系统,做这种任务做得多了,我之前写了一个叫django-data-importer的工具。这个导入工具的工作方式就像django的表单,它可以读取CSV、XLS和XLSX文件,并把内容转换成字典的列表。

使用data_importer的读取器,你可以把文件读成字典的列表,然后用for循环遍历这些数据,并把每一行保存到数据库里。这个导入工具不仅可以做到这些,还能额外检查每一行的字段是否正确,记录错误和操作,最后再保存数据。

请你看看这个链接:https://github.com/chronossc/django-data-importer。我相信它能解决你的问题,并帮助你处理任何类型的CSV文件,从现在开始会更方便哦 :)

为了帮助你解决问题,我建议你把data-importer和celery任务结合使用。你可以上传文件,然后通过一个简单的界面启动导入任务。celery任务会把文件发送给导入工具,你可以在这个过程中验证每一行的数据,保存它们,并记录错误。如果你愿意花点时间,还可以给上传文件的用户展示任务的进度。

2

把这个问题分成两个小问题怎么样?

首先,创建一个 Person 类,这个类用来表示数据库中的一个人。你可以使用 Django 的 ORM(对象关系映射),或者在此基础上进行扩展,或者自己来实现。

现在你有两个要解决的问题:

  1. 从 CSV 文件中的一行数据创建一个 Person 实例。
  2. 把这个 Person 实例保存到数据库中。

这样一来,你的工作就不再只是把 CSV 文件的数据放进数据库,而是变成了从 CSV 到 Person,再从 Person 到数据库。我觉得这样更清晰。当管理员修改数据库的结构时,只需要处理 Person 到数据库的部分;而当管理员修改 CSV 文件的格式时,只需要处理 CSV 到数据库的部分。这样你就可以分别处理这两个问题了。

这样说有没有帮助呢?

0

我最后采取了一些步骤来解决这个问题,遵循奥卡姆剃刀原则,使用可更新的SQL视图。这意味着我做了一些妥协:

  1. 去掉了:依赖South.DB的实时模式管理API、动态模型加载和动态ORM同步
  2. 手动定义models.py和初始的south迁移。

这样做可以简单地将平面数据集(比如CSV或Excel文件)导入到一个规范化的数据库中:

  1. 在models.py中为每个电子表格定义不受管理的模型
  2. 将这些模型映射到可更新的SQL视图(使用INSERT/UPDATE替代的SQL规则),并在初始的south迁移中遵循电子表格的字段布局
  3. 遍历CSV/Excel电子表格的每一行,执行一个INSERT INTO <VIEW> (<COLUMNS>) VALUES (<CSV-ROW-FIELDS>);

撰写回答