2010-04-28 36 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 2010-04-29 15:43:14

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 2010-04-29 15:42:44

+0

但請注意,這隻適用於包含一個點的文件名。具有多個點的文件名將打破驗證。相反,使用這樣的東西:(短名稱,擴展名)= os.path.splitext(文件名)。 – Jens 2010-04-30 02:31:25

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)