【问题标题】:Django, Python: Best way to parse a CSV and convert to Django model instancesDjango, Python:解析 CSV 并转换为 Django 模型实例的最佳方法
【发布时间】:2018-06-14 09:54:08
【问题描述】:

我有一个用户上传 CSV 文件的页面。这一点有效。

我可以读取 CSV 并将其转换为列表。我认为应该更快的东西需要相当长的时间(对于 17mb 的 CSV 文件,解析并将其转换为列表大约需要 7 秒)。

我现在想知道,这样做的最佳方法是什么?到目前为止我的代码非常复杂(很久以前由一个已经离开的 CS 研究生同事写的),我想我想重写它,因为它太慢了。

我以前没有使用过 CSV。现在这就是我所拥有的:

import codecs
import csv
import sys

def read_csv_file(self, file_path):
    is_file = False
    while not is_file:
        if os.path.exists(file_path):
            is_file = True
    result_data = []

    csv.field_size_limit(sys.maxsize)

    csv_reader = csv.reader(codecs.open(file_path, 'rU', 'utf-8'), delimiter=',')

    for row in csv_reader:
        result_data.append(row)

    return result_data

将 CSV 转换为列表(然后我可以压缩?)是最好的方法吗?

最终,目标是创建 DB 对象(也许是在循环中?),这类似于循环遍历每个列表,使用索引创建对象,将这些对象附加到对象列表,然后执行 bulk_create:

object_instance_list.append(My_Object.objects.get_or_create(property=csv_property[some_index], etc etc)[0])
My_Object.bulk_create(object_instance_list)

这样会有效吗?

我应该改用 dicts 吗?

是否有一个内置方法允许 Python 的 CSV 或一些已经完成的 Django 功能?

基本上,由于我没有这种经验,而且这是我第一次使用 CSV,我想从一开始就做好(ish)。

我将不胜感激这方面的任何帮助,因此我可以学习处理此问题的正确方法。谢谢!

【问题讨论】:

  • 我猜你最好使用字典模式。
  • 您如何定义“最佳”?如果您的 "best" 是最大速度,那么最佳解决方案将是:绕过 django 并直接从 csv 将记录导入 db-table。
  • "Best" 将是速度和效率,在 Django 参数内。 CSV 的上传以及选择正确的文件并将处理它的请求发送到我的网络服务器已经完成。处理是我停止的地方。理想情况下,我需要一个可以发送回 Django bulk_create 构造函数的对象列表。这主要是我不知道如何解决的中间问题。

标签: python django csv


【解决方案1】:

因此,这是未经测试的,但从概念上讲,您应该能够理解。诀窍是利用**kwargs

import csv

def read_csv():
    """Read the csv into dictionaries, transform the keys necessary
    and return a list of cleaned-up dictionaries.
    """
    with open('data.csv', newline='') as csvfile:
        reader = csv.DictReader(csvfile)
        return [map_rows_to_fields(row) for row in reader]

def map_rows_to_fields(row):
    """Here for each dictionary you want to transform the dictionary
    in order to map the keys of the dict to match the names of the
    fields on the model you want to create so we can pass it in as
    `**kwargs`. This would be an opportunity to use a nice dictionary
    comprehension.
    """
    csv_fields_to_model_fields = {
        'csv_field_1': 'model_field_1',
        'csv_field_2': 'model_field_2',
        'csv_field_n': 'model_field_n',
    }
    return {
        csv_fields_to_model_fields[key]: value
        for key, value in row.items()
    } 

def instantiate_models():
    """Finally, we have our data from the csv in dictionaries
    that map values to expected fields on our model constructor,
    then we can just instantiate each of those models from the
    dictionary data using a list comprehension, the result of which
    we pass as the argument to `bulk_create` saving the rows to 
    the database.
    """
    model_data = read_csv()
    MyModel.objects.bulk_create([
        MyModel(**data) for data in model_data
    ])

bulk_create 方法确实有一些注意事项,因此请确保可以在您的情况下使用它。

https://docs.djangoproject.com/en/2.0/ref/models/querysets/#bulk-create

如果您不能使用bulk_create,那么只需循环制作模型即可。

for data in model_data:
    MyModel.objects.create(**data)

【讨论】:

  • 在这种情况下通过 bulk_create 创建是有效的。我还有其他一些情况,我正在这样做。它还可以节省大量时间。
  • 好东西,我只是为其他可能看到答案的人介绍边缘情况。
  • 您的回答很棒。我主要想看看我是否应该使用列表或字典,以及什么是好的方法。感谢您的帮助!
猜你喜欢
  • 2011-01-05
  • 1970-01-01
  • 2015-04-29
  • 2015-02-11
  • 2013-12-20
  • 2012-07-14
  • 2021-10-29
  • 2022-01-25
  • 1970-01-01
相关资源
最近更新 更多