如何使用Django表单验证CSV文件的内容

时间:2013-05-03 23:30:50

标签: django csv django-forms

我有一个需要执行以下操作的网络应用程序:

1)提交表单以请求客户端文件进行CSV导入。 2)验证CSV文件中的数据或询问另一个文件名。

有一次,在获取文件名的form.is_valid()调用之后,我在视图中进行了CSV数据验证(即我使用csv.DictReader将导入的CSV文件导入到字典的内存中)。在尝试将错误传回原始表单时遇到问题后,我现在尝试使用表单的clean()方法验证CSV文件的CONTENTS。

我目前难以理解如何从clean()访问内存文件,因为request.FILES对象无效。请注意,将表单呈现给客户端浏览器然后操作生成的CSV文件没有问题。真正的问题是如何验证CSV文件的内容 - 如果我假设数据格式是正确的,我可以将其导入我的模型。我将发布我的forms.py文件,以便在将代码从视图移动到表单后显示我当前的位置:

forms.py

import csv
from django import forms
from io import TextIOWrapper


class CSVImportForm(forms.Form):
    filename = forms.FileField(label='Select a CSV file to import:',)

    def clean(self):
        cleaned_data = super(CSVImportForm, self).clean()

        f = TextIOWrapper(request.FILES['filename'].file, encoding='ASCII')
        result_csvlist = csv.DictReader(f)
        # first line (only) contains additional information about the event
        # let's validate that against its form definition
        event_info = next(result_csvlist)
        f_eventinfo = ResultsForm(event_info)
        if not f_eventinfo.is_valid():
            raise forms.ValidationError("Error validating 1st line of data (after header) in CSV")

        return cleaned_data

class ResultsForm(forms.Form):
    RESULT_CHOICES = (('Won', 'Won'),
                      ('Lost', 'Lost'),
                      ('Tie', 'Tie'),
                      ('WonByForfeit', 'WonByForfeit'),
                      ('LostByForfeit', 'LostByForfeit'))

    Team1 = forms.CharField(min_length=10, max_length=11)
    Team2 = forms.CharField(min_length=10, max_length=11)
    Result = forms.ChoiceField(choices=RESULT_CHOICES)
    Score = forms.CharField()
    Event = forms.CharField()
    Venue = forms.CharField()
    Date = forms.DateField()
    Div = forms.CharField()
    Website = forms.URLField(required=False)
    TD = forms.CharField(required=False)

我喜欢输入验证上传的CSV文件内容的“最佳”方法,并将该信息反馈给客户端浏览器!

1 个答案:

答案 0 :(得分:2)

我假设当你要访问该文件时,clean方法中的这行是

f = TextIOWrapper(request.FILES['filename'].file, encoding='ASCII')

您无法使用该行,因为request不存在,但您可以访问表单的字段,以便您可以尝试使用此字段:

f = TextIOWrapper(self.cleaned_data.get('filename'), encoding='ASCII')

由于您在方法的第一行中已完成super.clean,因此应该可以使用。然后,如果要向表单添加自定义错误消息,可以这样做:

from django.forms.util import ErrorList
errors = form._errors.setdefault("filename", ErrorList())
errors.append(u"CSV file incorrect")

希望它有所帮助。