2

I have a web app that needs to do the following:

  1. Present a form to request a client side file for CSV import.
  2. Validate the data in the CSV file or ask for another filename.

At one point, I was doing the CSV data validation in the view, after the form.is_valid() call from getting the filename (i.e. I have the imported CSV file into memory in a dictionary using csv.DictReader). After running into problems trying to pass errors back to the original form, I'm now trying to validate the CONTENTS of the CSV file in the form's clean() method.

I'm currently stumped on how to access the in memory file from clean() as the request.FILES object isn't valid. Note that I have no problems presenting the form to the client browser and then manipulating the resulting CSV file. The real issue is how to validate the contents of the CSV file - if I assume the data format is correct I can import it to my models. I'll post my forms.py file to show where I currently am after moving the code from the view to the form:

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)

I'd love input on what's the "best" method to validate the contents of an uploaded CSV file and present that information back to the client browser!

4

1 回答 1

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")

希望能帮助到你。

于 2013-05-04T01:37:38.620 回答