【问题标题】:Importing a CSV file into a PostgreSQL DB using Python-Django使用 Python-Django 将 CSV 文件导入 PostgreSQL 数据库
【发布时间】:2013-03-18 05:15:19
【问题描述】:

注意:向下滚动到背景部分以获取有用的详细信息。假设项目使用 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. 管理员用户可以通过自定义 UI 实时更改数据库模型和 CSV 导入表示
  2. 普通用户导入 CSV 文件时使用保存的 CSV 到数据库的表/字段映射

目前已经考虑了两种方法

  1. ETL-API 方法:为 ETL API 提供电子表格、我的 CSV 到数据库表/字段映射以及与目标数据库的连接信息。然后 API 将加载电子表格并填充目标数据库表。看着 pygrametl 我不认为我的目标是可能的。事实上,我不确定是否有任何 ETL API 可以做到这一点。
  2. 行级插入方法:解析 CSV 到数据库的表/字段映射,解析电子表格,并以“连接顺序”生成 SQL 插入。

我实现了第二种方法,但在算法缺陷和代码复杂性方面遇到了困难。那里有没有我想要的python ETL API?还是一种不涉及重新发明轮子的方法?


背景

我工作的公司正在寻求将 Sharepoint 中托管的数百个特定于项目的设计电子表格转移到数据库中。通过允许管理员为每个项目定义/建模数据库、在其中存储电子表格并定义浏览体验,我们即将完成满足需求的 Web 应用程序。在这个完成阶段,过渡到商业工具不是一种选择。将 Web 应用程序视为 django-admin 的替代方案,尽管它不是,它具有 DB 建模 UI、CSV 导入/导出功能、可定制的浏览和模块化代码来解决项目特定的定制问题。

实现的 CSV 导入界面既麻烦又麻烦,所以我正在尝试获得反馈并寻找替代方法。

【问题讨论】:

  • 我认为你应该具体化这个问题。提取您正在寻找的最小示例并将其发布。即写一个csv样本数据和规范化所需的目标架构。
  • 感谢您的建议。希望这会得到更多的关注。顺便说一句,现在更改标题。
  • 这个问题仍然没有意义。设计一个模式,把它放在那里,使用它——这是一个三线和/或psql调用。
  • 这不是 3-liner,它是财富 500 强公司的企业 Web 应用程序。该模式是动态的以满足业务需求,它并没有以这种方式开始,只有管理员可以通过 UI 更改它。涉及 CSV 导入解决方案是因为架构是动态的,因此无法解决。您提供的代码使用了静态模式,并且不包含 CSV 导入代码。如果您对如何澄清问题有任何建议,我很乐意将它们纳入其中。
  • 到目前为止,您还没有任何具体/唯一的标识符,这让我很担心。这两个示例中的前两个字段是说明同一个人,还是不同的人,还是未知? "john","doe","savings","personal", "john","doe","savings","business"

标签: python django postgresql etl pygrametl


【解决方案1】:

把问题分成两个独立的问题怎么样?

创建一个Person 类,它代表数据库中的一个人。这可以使用 Django 的 ORM,或者扩展它,或者你可以自己做。

现在你有两个问题:

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

现在,您不仅可以使用 CSV 到数据库,还可以使用 CSV 到个人和个人到数据库。我认为这在概念上更清洁。当管理员更改架构时,会更改人员到数据库端。当管理员更改 CSV 格式时,他们正在更改 CSV-to-Database 端。现在你可以分别处理每一个。

这有帮助吗?

【讨论】:

  • Person 将是许多动态创建的对象之一,因为整个模型是动态的;不仅仅是字段,表格也是如此。由于每个对象都是一个实例,并且对象是层次相关的,因此持久性将要求在树的每个“步骤”中进行行级插入。这绝对值得考虑,并且与行级插入方法非常相似。
  • 希望我能将赏金提高到 100 以提供更好的激励
  • 为什么要求管理员可以完全更改架构?也许知道这会帮助我想到一些事情。
  • Web 应用程序用业务驱动的项目数据替换了一个共享点存储库,该存储库维护大量的 Excel 电子表格。该应用程序最初跟踪一个项目。该项目和使用的电子表格随着时间的推移而变化,需要动态的现场支持。随着范围扩大到包括其他项目,很明显正确的解决方案是具有模块化项目逻辑的模型无关工具。简而言之,该应用程序是专有的数据库建模工具,具有导入、浏览、导出和搜索界面;和模块化的项目特定的“业务逻辑”。
  • 当前动态模型在需要它们的代码中是如何实际使用的?他们是否运行自定义 SQL 查询并在管理员更改架构时更新这些查询?他们是否直接对 .csv 文件进行操作并在这些 .csv 文件更改时更改其代码?他们是否有一个 ORM,每当模型发生变化时都必须以某种方式更新?
【解决方案2】:

我几乎每个月都在工作中编写导入子系统,并且当我执行此类任务时,我前段时间写了很多 django-data-importer。这个导入器的工作方式类似于 django 表单,并具有 CSV、XLS 和 XLSX 文件的阅读器,可为您提供字典列表。

使用 data_importer 阅读器,您可以将文件读取到 dicts 列表中,并使用 for 和 save 行进行数据库迭代。 使用导入器,您可以执行相同操作,但可以验证行的每个字段,记录错误和操作,并在最后保存。

请看一下https://github.com/chronossc/django-data-importer。我很确定它会解决您的问题,并且从现在开始可以帮助您处理任何类型的 csv 文件:)

为了解决您的问题,我建议将数据导入器与 celery 任务一起使用。您可以通过一个简单的界面上传文件并触发导入任务。 Celery 任务会将文件发送到导入器,您可以验证行,保存它,为它记录错误。通过一些努力,您甚至可以为上传工作表的用户展示任务进度。

【讨论】:

  • 我需要解决的问题是,如何根据定义每个字段所属的表以及这些表如何关联的映射,智能地将整个 CSV 数据集提交到数据库。您的导入器可以为行级插入方法的更清洁实施做出贡献。
  • Importer 在这一点上可能没有帮助,因为它需要定义的字段范围,但 data_importer.readers 会有所帮助。由于它保存了一些将每行返回为字典的代码,因此您可以拥有一个像 {'fieldname': , ...} 这样的字典,并在字典的循环中调用 functions_dict[fieldname](fieldvalue, row)。该函数在正确的位置完成保存的工作,这里是一个示例:gist.github.com/chronossc/5208763 您可以使用仅对实例进行价值归因并在所有保存实例之后进行的函数来改进它。
【解决方案3】:

我最终后退几步,使用可更新的 SQL 视图解决了奥卡姆剃刀的问题。这意味着一些牺牲:

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

这允许一种将平面数据集 (CSV/Excel) 导入规范化数据库的简单方法:

  1. 在 models.py 中为每个电子表格定义非托管模型
  2. 在遵循电子表格字段布局的初始南迁移中将它们映射到可更新的 SQL 视图(INSERT/UPDATE-INSTEAD SQL RULE)
  3. 遍历 CSV/Excel 电子表格行并执行 INSERT INTO <VIEW> (<COLUMNS>) VALUES (<CSV-ROW-FIELDS>);

【讨论】:

    【解决方案4】:

    这是我在 github 上找到的另一种方法。基本上它会检测架构并允许覆盖。它的全部目标是只生成要由 psql 或任何驱动程序执行的原始 sql。

    https://github.com/nmccready/csv2psql

      % python setup.py install
      % csv2psql --schema=public --key=student_id,class_id example/enrolled.csv > enrolled.sql
      % psql -f enrolled.sql
    

    还有很多选项可以进行更改(从许多现有的列创建主键)和合并/转储。

    【讨论】:

      猜你喜欢
      • 2017-03-11
      • 2021-10-20
      • 2013-02-19
      • 2018-05-02
      • 1970-01-01
      • 2011-02-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多