Login

CSVField for forms

Author:
AgustinLado
Posted:
December 22, 2016
Language:
Python
Version:
Not specified
Tags:
forms csv field
Score:
0 (after 0 ratings)

FileField that checks that the file is a valid CSV and if specified in expected_fieldnames checks that the fields match exactly.

The widget's accept parameter is set to accept csv, text and excel files.

TODO: Validate the entirety of the CSV file, not just the headers. But this should be enough for most use cases, as checking the whole file could be computationally expensive for huge files.

Example usage: people = CSVField(expected_fieldnames=['First Name', 'Last Name'])

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import csv

from django import forms
from django.core.exceptions import ValidationError


class CSVField(forms.FileField):
    """
    FileField that checks that the file is a valid CSV and if specified
    in `expected_fieldnames` checks that the fields match exactly.

    The widget's `accept` parameter is set to accept csv, text and excel files.

    TODO: Validate the entirety of the CSV file, not just the headers.
          But this should be enough for most use cases, as checking the 
          whole file could be computationally expensive for huge files.

    Example usage:
        people = CSVField(expected_fieldnames=['First Name', 'Last Name'])
    """

    def __init__(self, *args, **kwargs):
        self.expected_fieldnames = kwargs.pop('expected_fieldnames', None)
        super(CSVField, self).__init__(*args, **kwargs)
        self.error_messages['required'] = 'You must select a file'
        self.widget.attrs.update(
            {'accept': '.csv,'
                       'text/plain,'
                       'application/vnd.ms-excel,'
                       'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'})

    def clean(self, data, initial=None):
        value = super(CSVField, self).clean(data)
        reader = csv.reader(data)
        # Check it's a valid CSV file
        try:
            fieldnames = reader.next()
        except csv.Error:
            raise ValidationError('You must upload a valid CSV file')

        # Check the fieldnames are as specified, if requested
        if self.expected_fieldnames and fieldnames != self.expected_fieldnames:
            raise ValidationError(
                u'The CSV fields are expected to be "{0}"'.format(
                    u','.join(self.expected_fieldnames)))

        return value

More like this

Comments

Please login first before commenting.