【问题标题】:Iterate over and validate large uploaded CSV files in Django在 Django 中迭代并验证上传的大型 CSV 文件
【发布时间】:2019-02-25 02:11:58
【问题描述】:

我正在使用 Django 模块 django-chunked-upload 来接收可能较大的 CSV 文件。我可以假设 CSV 格式正确,但我不能假设分隔符是什么。

上传完成后,会返回一个UploadedFile 对象。我需要验证上传的 CSV 中是否包含正确的列,以及每列中的数据类型是否正确。

使用csv.reader() 加载文件不起作用:

reader = csv.reader(uploaded_file)
next(reader)
>>> _csv.Error: iterator should return strings, not bytes (did you open the file in text mode?)

这可能是因为uploaded_file.content_typeuploaded_file.charset 都以None 的身份出现。

我想出了一个相当不优雅的解决方案来获取标题并遍历行:

i = 0
header = ""
for line in uploaded_file:
    if i == 0:
        header = line.decode('utf-8')
        header_list = list(csv.reader(StringIO(header)))
        print(header_list[0])
        #validate column names
    else:
        tiny_csv = StringIO(header + line.decode('utf-8'))
        reader = csv.DictReader(tiny_csv)
        print(next(reader))
        #validate column types

我也考虑过尝试加载实际保存文件的路径:

path = #figure out the path of the temp file
f = open(path,"r")
reader = csv.reader(f)

但我无法从 UploadedFile 对象中获取临时文件路径。

理想情况下,我想从 UploadedFile 对象中创建一个普通的阅读器或 DictReader,但它似乎在逃避我。谁有想法? - 谢谢

【问题讨论】:

  • 你的'uploaded_file'是什么类型的,能打印出来看看。
  • 上面提供的链接是<class 'django.core.files.uploadedfile.UploadedFile'>。 (docs.djangoproject.com/en/2.1/_modules/django/core/files/…)
  • 我有一个线索,你能检查一下这是否解决了 'reader = csv.reader(uploaded_file.seek(0))' 解决了这个问题吗?
  • 有趣的是它吐出了一个不同的错误:reader = csv.reader(uploaded_file.seek(0)) TypeError: argument 1 must be an iterator
  • 如果你做 upload_file = upload_file.seek(0) 然后使用它会怎样。

标签: python django csv chunked


【解决方案1】:

答案就在 chunked_upload/models.py 中,其中有一行:

def get_uploaded_file(self):
    self.file.close()
    self.file.open(mode='rb')  # mode = read+binary
    return UploadedFile(file=self.file, name=self.filename,
                        size=self.offset)

因此,当您创建文件模型时,您可以选择使用mode='r' 打开文件:

#myapp/models.py

from django.db import models
from chunked_upload.models import ChunkedUpload
from django.core.files.uploadedfile import UploadedFile
class FileUpload(ChunkedUpload):
    def get_uploaded_file(self):
        self.file.close()
        self.file.open(mode='r')  # mode = read+binary
        return UploadedFile(file=self.file, name=self.filename,
                            size=self.offset)

这允许您获取返回的 UploadedFile 实例并将其解析为 csv:

def on_completion(self, uploaded_file, request):
    reader = csv.reader(uploaded_file)
    ...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-07-29
    • 2013-12-14
    • 2019-05-13
    • 2010-12-17
    • 2011-09-05
    • 2013-11-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多