How to validate contents of a CSV file using Django forms
csv, django, django-forms
Solution
I assume that when you want to access that file is in this line inside the `clean` method:
f = TextIOWrapper(request.FILES['filename'].file, encoding='ASCII')
You can't use that line because `request` doesn't exist but you can access your form's fields so you can try this instead:
f = TextIOWrapper(self.cleaned_data.get('filename'), encoding='ASCII')
Since you have done `super.clean` in the first line in your method, that should work. Then, if you want to add custom error message to you form you can do it like this:
from django.forms.util import ErrorList
errors = form._errors.setdefault("filename", ErrorList())
errors.append(u"CSV file incorrect")
Hope it helps.
Problem
I have a web app that needs to do the following: - Present a form to request a client side file for CSV import. - 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!