Django ModelForm:干净地编辑/替换FileField中的文件

时间:2019-08-01 17:29:14

标签: python django django-forms

我正在使用一个View,用户可以在其中上传csv文件。但是,根据过去的经验,我们知道这些用户上传的.csv文件的列名通常包含多余的空格,大写字母或较小的拼写错误,导致其余代码跳闸

(例如:[Username, E-mail, lastname']代替['username', 'email', 'lastname']

这些文件是使用ModelForm上传的,它们被附加到FileField模型的StudentImport

我想出了一个解决方案,其中我将使用clean_import_file方法检查标题,如果标题与预期的标题不匹配,请对其进行编辑。代码的那部分工作正常,但是在最后一步遇到了麻烦:用新编辑的文件覆盖原始(有缺陷的)文件。

class StudentImportForm(forms.ModelForm):

    class Meta:
        model = models.StudentImport
        fields = ['import_file']

    def save(self, commit=True):
        obj = super(StudentImportForm, self).save(commit=False)
        obj.created_by = self.created_by
        obj.file_type = self.file_type
        if commit:
            obj.save()
        return obj

    def clean_import_file(self):
        file = self.cleaned_data['import_file']

        df = pd.read_csv(
            pd.compat.StringIO(file.read())
        )
        file.seek(0)

        if list(df.columns) != EXPECTED_COLUMNS:
            og_columns = list(df.columns.copy())

            # Try minor fixes and see if this is enough
            df.columns = [x.lower() for x in df.columns]
            df.columns = [x.strip() for x in df.columns]
            df.columns = ['email' if 'mail' in x else x for x in df.columns]

            # Check if this is enough
            if list(df.columns) != EXPECTED_COLUMNS:
                raise forms.ValidationError(
                    'Column mismatch! Expected: {}, '
                    'received: {}'.format(EXPECTED_COLUMNS, og_columns)
                )

            file = StringIO()
            df.to_csv(file)

        return file

当我上传一个(有缺陷但可修复的).csv文件时,我遇到了 AttributeError: StringIO instance has no attribute '_committed'错误。

由于StringIO对象似乎缺少必需的参数,我希望基于ContentFile的方法可以解决该问题,

    file = ContentFile(df.to_csv)
    self.cleaned_data['import_file'] = file 

return file

此代码本身并未引发任何错误,但是由于该表单现在抱怨import_file字段为空,因此未能上传有效文件。

我过去曾使用StringIO对象链接到Django模型,所以我尚不完全清楚为什么这种方法现在会失败。有人知道我在做什么错吗?

0 个答案:

没有答案