2010-04-28 5 views
2

Я написал приложение, которое использует формы для сбора информации, которая затем отправляется по электронной почте. Многие из этих форм имеют файловое поле, используемое для прикрепления файлов к электронной почте. Я хотел бы проверить две вещи: размер файла (чтобы гарантировать, что электронные письма приняты нашим почтовым сервером. Я также хотел бы проверить расширение файла, чтобы препятствовать прикреплению типов файлов, которые не используются для наших пользователей.Расширение поля формы, чтобы добавить новые проверки

(Это класс питона я пытаюсь расширить)

class FileField(Field): 
    widget = FileInput 
    default_error_messages = { 
     'invalid': _(u"No file was submitted. Check the encoding type on the form."), 
     'missing': _(u"No file was submitted."), 
     'empty': _(u"The submitted file is empty."), 
     'max_length': _(u'Ensure this filename has at most %(max)d characters (it has %(length)d).'), 
    } 

    def __init__(self, *args, **kwargs): 
     self.max_length = kwargs.pop('max_length', None) 
     super(FileField, self).__init__(*args, **kwargs) 

    def clean(self, data, initial=None): 
     super(FileField, self).clean(initial or data) 
     if not self.required and data in EMPTY_VALUES: 
      return None 
     elif not data and initial: 
      return initial 

     # UploadedFile objects should have name and size attributes. 
     try: 
      file_name = data.name 
      file_size = data.size 
     except AttributeError: 
      raise ValidationError(self.error_messages['invalid']) 

     if self.max_length is not None and len(file_name) > self.max_length: 
      error_values = {'max': self.max_length, 'length': len(file_name)} 
      raise ValidationError(self.error_messages['max_length'] % error_values) 
     if not file_name: 
      raise ValidationError(self.error_messages['invalid']) 
     if not file_size: 
      raise ValidationError(self.error_messages['empty']) 
    return data 

ответ

2

Просто перегружать «чистый» метод:

def clean(self, data, initial=None): 
    try: 
     if data.size > somesize: 
      raise ValidationError('File is too big') 

     (junk, ext) = os.path.splitext(data.name) 
     if not ext in ('.jpg', '.gif', '.png'): 
      raise ValidationError('Invalid file type') 

    except AttributeError: 
     raise ValidationError(self.error_messages['invalid']) 

    return FileField.clean(self, data, initial) 
+0

я оказался следующим ваш метод. Спасибо за вашу помощь! – duallain

1

на мой взгляд подклассов фактический класс поля является способ особых усилий Вам будет проще просто расширить класс формы. Можно добавить метод, который «очищает» t он поле файла.

Например:

class MyForm(forms.Form): 
    attachment = forms.FileField(...) 

    def clean_attachment(self): 
    data = self.cleaned_data['attachment'] // UploadedFile object 
    exts = ['jpg', 'png'] // allowed extensions 

    // 1. check file size 
    if data.size > x: 
     raise forms.ValidationError("file to big") 

    // 2. check file extension 
    file_extension = data.name.split('.')[1] // simple method 

    if file_extension not in exts: 
     raise forms.ValidationError("Wrong file type") 

    return data 

Это лишь простой пример, и есть некоторые шероховатости. Но вы можете использовать этот пример и улучшить его, пока у вас не будет версии, которая будет работать для вас.

Рекомендуется к прочтению:

Django Doc - Cleaning a specific field

Django Doc - UploadedFile class

Django Doc - File class

+0

Благодарим вас за ответ. Я закончил использование вашего метода для выполнения проверки расширения. Я решил реализовать подкласс, потому что эта проверка должна была быть выполнена для примерно 20 форм. Ваш мета-метод будет полезен для проверки некоторых других полей. – duallain

+0

Но имейте в виду, что это будет работать только для имен файлов, содержащих одну точку. Имена файлов с несколькими точками нарушают валидацию. Вместо этого используйте что-то вроде этого: (shortname, extension) = os.path.splitext (имя файла). – Jens

0

Это то, что я в конечном итоге делает:

В файле настройки моего приложения:

exts = ['doc', 'docx', 'pdf', 'jpg', 'png', 'xls', 'xlsx', '.xlsm', '.xlsb'] 
max_email_attach_size = 10485760 #10MB written in bytes 

В новом файле я назвал formfunctions:

from django import forms 
from django.forms.util import ErrorList, ValidationError 
from app.settings import exts, max_email_attach_size 


class SizedFileField(forms.FileField): 

    def clean(self, data, initial=None): 

     if not data in (None, ''): 

      try: 
       if data.size > max_email_attach_size: 
        raise ValidationError("The file is too big") 

       file_extension = data.name.split('.')[1] 
       if file_extension not in exts: 
        raise ValidationError("Invalid File Type") 

      except AttributeError: 
       raise ValidationError(self.error_messages['invalid']) 

     return forms.FileField.clean(self, data, initial) 

и в моих формах ФАЙЛ:

from formfunctions import SizedFileField 

Пример класс из файла форм:

class ExampleClass(forms.Form): 
    Email_Body = forms.CharField(widget=forms.Textarea, required=False) 
    Todays_Date = forms.CharField() 
    Attachment = SizedFileField(required=False) 
Смежные вопросы