开发者

How to use the ExtFileField snippet?

As i want to restrict the fileupload to certain types of audiofiles, i found that django snippet http://djangosnippets.org/snippets/977/, that is restricting the fileupload to files within an extension whitelist:

class ExtFileField(forms.FileField):
"""
Same as forms.FileField, but you can specify a file extension whitelist.

开发者_如何学JAVA>>> from django.core.files.uploadedfile import SimpleUploadedFile
>>>
>>> t = ExtFileField(ext_whitelist=(".pdf", ".txt"))
>>>
>>> t.clean(SimpleUploadedFile('filename.pdf', 'Some File Content'))
>>> t.clean(SimpleUploadedFile('filename.txt', 'Some File Content'))
>>>
>>> t.clean(SimpleUploadedFile('filename.exe', 'Some File Content'))
Traceback (most recent call last):
...
ValidationError: [u'Not allowed filetype!']
"""
def __init__(self, *args, **kwargs):
    ext_whitelist = kwargs.pop("ext_whitelist")
    self.ext_whitelist = [i.lower() for i in ext_whitelist]

    super(ExtFileField, self).__init__(*args, **kwargs)

def clean(self, *args, **kwargs):
    data = super(ExtFileField, self).clean(*args, **kwargs)
    filename = data.name
    ext = os.path.splitext(filename)[1]
    ext = ext.lower()
    if ext not in self.ext_whitelist:
        raise forms.ValidationError("Not allowed filetype!")  

In my forms i have a standard FileField until now. That uploads the file, saves it and works perfectly well. Then i substitute the FileField with it like this

class NewItemForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
    super(NewItemForm, self).__init__(*args, **kwargs)
    self.fields['file']=ExtFileField(ext_whitelist=(".wav", ".aif", ".flac"))

class Meta:
    model = Item
    fields = ('file','name','meta1','tags')  

when trying to upload any file not in the whitelist i get the error message "Not allowed filetype!", which is good. But when uploading a file within the whitelist i get the error message "This field cannot be blank.", which i do not understand. I just have the suspicion it has something to do with the way i replaced the filefield from the modelform. What would be the right way to do it?


At the end of the 'clean' method, make sure you return data so that the normal clean method of forms.FileField has access to it. In the current implementation you have (which is directly from the snippet), the forms.FileField clean method will not get the uploaded file.

I also needed to adjust my method since I had fields that were not required. As a result, the implementation would fail trying to access the name property of data (since data is None).

Lastly, you can do this same sort of file whitelisting with content types (not shown below), where instead of checking the extension you would check data.file.content_type against a content_whitelist param that you would pass into your field constructor (in the same fashion as ext_whitelist).

def clean(self, *args, **kwargs):
    data = super(ExtFileField, self).clean(*args, **kwargs)
    if data:
        filename = data.name
        ext = os.path.splitext(filename)[1]
        ext = ext.lower()
        if ext not in self.ext_whitelist:
            raise forms.ValidationError("Filetype '%s' not allowed for this field" % ext)
    elif not data and self.required:
        raise forms.ValidationError("Required file not found for %s" % self.label)
    return data


The proper way to override a field on a modelform is just to declare the field at the class level:

class NewItemForm(forms.ModelForm):
    file = ExtFileField(ext_whitelist=(".wav", ".aif", ".flac"))
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜