django-import-export csv 前的空行 header 导入时触发异常

django-import-export empty rows before csv header trigger exception while importing

从 csv 导入数据时,我意识到如果第一行不是 header

,就会触发此错误

list indices must be integers or slices, not str


first_name,last_name,email,password,role
Noak,Larrett,nlarrett0@ezinearticles.com,8sh15apPjI,Student
Duffie,Milesap,dmilesap1@wikipedia.org,bKNIlIWVfNw,Student

仅当第一行是 header

时才有效
first_name,last_name,email,password,role
Noak,Larrett,nlarrett0@ezinearticles.com,8sh15apPjI,Student
Duffie,Milesap,dmilesap1@wikipedia.org,bKNIlIWVfNw,Student

...

我尝试覆盖 before_import 以删除任何空白行

def before_import(self, dataset, using_transactions, dry_run, **kwargs):
    indexes = []
    for i in range(0, len(dataset)):
        row = ''.join(dataset[i])
        if row.strip() == '':
            indexes.append(i)
    for index in sorted(indexes, reverse=True):
        del dataset[index]          
    return dataset

这适用于所有行,除了第一行应该始终包含 header,否则将抛出错误。

经过几个小时的调试,我找到了 ImportMixin class,它位于 import_export/admin.py

class 包含一个名为 import_action 的方法,看起来像这样

def import_action(self, request, *args, **kwargs):
    ...
    import_file = form.cleaned_data['import_file']
    ...
    data = tmp_storage.read(input_format.get_read_mode())
    ...
    dataset = input_format.create_dataset(data)
    ...

如您所见,这是在将上传文件传递给 input_format.create_dataset() 之前将其读取为字符串的函数。所以我所要做的就是添加一个自定义函数来删除空行

data = self.remove_blanks(data)
dataset = input_format.create_dataset(data)

import_export/admin.py/ImportMixin

def remove_blanks(self, data):
    return os.linesep.join([s for s in data.splitlines() if s.strip()])

这样任何 csv 文件都不会有任何空行,这将强制第一行成为 header 并解决问题。我希望这对面临同样问题的任何人都有用。

UPDATE :还有一种简单的方法可以通过在 import_export/formats/base_formats.py

中覆盖 create_dataset 来实现相同的目的

import_export/formats/base_formats.py/TablibFormat

def create_dataset(self, in_stream, **kwargs):
    in_stream = os.linesep.join([s for s in in_stream.splitlines() if s.strip()])
    try:
        return tablib.import_set(in_stream, format=self.get_title())
    except:
        return tablib.import_set('', format=self.get_title())