2017-07-18 27 views
1

我有一個帶有文件區的Post模型,用於上傳文件。我如何驗證文件類型(現在是pdf還是其他類型,如果我稍後再更改)。最好我想驗證內容,但如果沒有,我猜後綴也會。我試圖在網上查找,但我發現的大多數解決方案都是從頭回來的,隨着Django文檔更新,他們不再工作。如果有人能幫忙,請幫忙。謝謝。驗證Django中的上傳文件類型

class Post(models.Model): 
    author = models.ForeignKey('auth.User',default='') 
    title = models.CharField(max_length=200) 
    text = models.TextField() 
    PDF = models.FileField(null=True, blank=True) 
    created_date = models.DateTimeField(
      default=timezone.now) 
    published_date = models.DateTimeField(
      blank=True, null=True) 

    def publish(self): 
     self.published_date = timezone.now() 
     self.save() 

    def __str__(self): 
     return self.title 
+0

我建議使用https://github.com/ahupp/python-magic – diek

回答

3

使用Django 1.11,您可以使用FileExtensionValidator。使用較早的版本或額外的驗證,您可以基於它創建自己的驗證器。你可能需要創建一個驗證器無論哪種方式,因爲這樣的警告:

Don’t rely on validation of the file extension to determine a file’s type. Files can be renamed to have any extension no matter what data they contain.

下面是一個示例代碼與現有的驗證:

from django.core.validators import FileExtensionValidator 
class Post(models.Model): 
    PDF = models.FileField(null=True, blank=True, validators=[FileExtensionValidator(['pdf'])]) 

源代碼也可以讓您可以輕鬆創建自己的:

https://docs.djangoproject.com/en/1.11/_modules/django/core/validators/#FileExtensionValidator

+0

這個方法我試過,但得到返回錯誤消息NameError:名稱'FileExtensionValidator'未定義 – hakuro

+0

那麼您必須首先導入它。我更新了答案。還要確保你使用的是Django 1.11。否則,你需要基於鏈接的源代碼自己實現它。 – kichik

+0

感謝您的解決方案。它現在很好用,但是當我更新錯誤的類型文件時,它給出了一個錯誤消息,它有一個有趣的方式來解析後綴:文件擴展名'xlsx'是不允許的。允許的擴展名是:'p,d,f'。猜猜我仍然需要弄清楚如何編寫我自己的驗證器的內容。 – hakuro

1

首先,我建議你改變 'PDF' 到 'PDF',然後在 OL驗證的Django的DER版本,你可以這樣做

forms.py

class PostForm(forms.ModelForm): 
    # fields here 
    class Meta: 
     model = Post 
     fields = ["title", "text", "pdf"] 

    def clean(self): 
     cd = self.cleaned_data 
     pdf = cd.get('pdf', None) 
     if pdf is not None: 
      main, sub = pdf.content_type.split('/') 
      # main here would most likely be application, as pdf mime type is application/pdf, 
      # but I'd like to be on a safer side should in case it returns octet-stream/pdf 
      if not (main in ["application", "octet-stream"] and sub == "pdf"): 
       raise forms.ValidationError(u'Please use a PDF file') 
     return cd 
+0

當我上傳一個文件時,這很好用,但當我嘗試編輯我的文件並刪除附件時出現錯誤 – hakuro

0

驗證考慮這樣的語句:

  • 名稱/擴展
  • 元數據(內容類型,大小)
  • 實際內容(實際上是內容類型說的PNG,還是惡意PDF?)

前兩個大多是化妝品 - 很容易欺騙/僞造該信息。通過添加內容驗證(通過文件魔術 - https://pypi.python.org/pypi/filemagic),您添加了一點額外的保護

這是一個很好的,相關的答案:Django: Validate file type of uploaded file它可能是舊的,但核心思想應該很容易適應。

0

下面是與文件類型驗證表單基於Django的1.11 FileExtensionValidator

一個簡單的例子
class ImageForm(ModelForm): 
    ALLOWED_TYPES = ['jpg', 'jpeg', 'png', 'gif'] 

    class Meta: 
     model = Profile 
     fields = ['image', ] 

    def clean_avatar(self): 
     image = self.cleaned_data.get('image', None) 
     if not avatar: 
      raise forms.ValidationError('Missing image file') 
     try: 
      extension = os.path.splitext(image.name)[1][1:].lower() 
      if extension in self.ALLOWED_TYPES: 
       return avatar 
      else: 
       raise forms.ValidationError('File types is not allowed') 
     except Exception as e: 
      raise forms.ValidationError('Can not identify file type')