遍历并验证Django中上传的大型CSV文件

时间:2018-09-20 17:51:09

标签: python django csv chunked

我正在使用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,但这似乎使我望而却步。有人有想法么? -谢谢

1 个答案:

答案 0 :(得分:0)

答案在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)
    ...