web-dev-qa-db-ja.com

FileFieldsを使用したModelFormsのファイルアップロードでファイルタイプを制限するにはどうすればよいですか?

私の目標は、Django ModelFormのFileFieldをPDFとWordドキュメントに制限することです。私がグーグルで検索した答えはすべて、個別のファイルハンドラーの作成を扱っていますが、その方法がわかりません。 ModelFormのコンテキスト。setups.pyにアップロードファイルの種類を制限するために使用できる設定はありますか?

21

ModelFormでclean_ [your_field]メソッドを使用してこれを処理します。クリーンなメソッドでチェックするためにsettings.pyに受け入れ可能なファイル拡張子のリストを設定できますが、アップロードの種類を制限するための組み込みのsettings.pyはありません。

たとえば、Django-Filebrowserは、settings.pyで受け入れ可能なファイル拡張子のリストを作成するアプローチを採用しています。

それがあなたを助けることを願っています。

0
Brandon

次のような検証メソッドを作成します。

def validate_file_extension(value):
    if not value.name.endswith('.pdf'):
        raise ValidationError(u'Error message')

次のようにFileFieldバリデーターに含めます。

actual_file = models.FileField(upload_to='uploaded_files', validators=[validate_file_extension])

また、モデルで許可する拡張機能を手動で設定する代わりに、setting.pyにリストを作成し、それを繰り返す必要があります。

編集

複数のファイルをフィルタリングするには:

def validate_file_extension(value):
  import os
  ext = os.path.splitext(value.name)[1]
  valid_extensions = ['.pdf','.doc','.docx']
  if not ext in valid_extensions:
    raise ValidationError(u'File not supported!')

ファイル名の拡張子を使用して検証することは、一貫した方法ではありません。たとえば、picture.jpgの名前をpicture.pdfに変更しても、検証でエラーが発生することはありません。

より良いアプローチは、ファイルのcontent_typeをチェックすることです。

検証方法

def validate_file_extension(value):
    if value.file.content_type != 'application/pdf':
        raise ValidationError(u'Error message')

使用法

actual_file = models.FileField(upload_to='uploaded_files', validators=[validate_file_extension])
23
Charlesthk

それを行う簡単な方法は、以下のフォームにあります

file = forms.FileField(widget=forms.FileInput(attrs={'accept':'application/pdf'}))
8
savp

より一般的な使用法として、Djangoの組み込みのExtensionValidatorを拡張する小さなクラスRegexValidatorを作成しました。オプションのカスタムエラーメッセージだけでなく、単一または複数の拡張子を受け入れます。

class ExtensionValidator(RegexValidator):
    def __init__(self, extensions, message=None):
        if not hasattr(extensions, '__iter__'):
            extensions = [extensions]
        regex = '\.(%s)$' % '|'.join(extensions)
        if message is None:
            message = 'File type not supported. Accepted types are: %s.' % ', '.join(extensions)
        super(ExtensionValidator, self).__init__(regex, message)

    def __call__(self, value):
        super(ExtensionValidator, self).__call__(value.name)

これで、フィールドにインラインでバリデーターを定義できます。例:

my_file = models.FileField('My file', validators=[ExtensionValidator(['pdf', 'doc', 'docx'])])
5
Shovalt

私はこれらの線に沿って何かを使用します(これには「pipinstallfilemagic」が必要です...):

import magic
def validate_mime_type(value):
    supported_types=['application/pdf',]
    with magic.Magic(flags=magic.MAGIC_MIME_TYPE) as m:
        mime_type=m.id_buffer(value.file.read(1024))
        value.file.seek(0)
    if mime_type not in supported_types:
        raise ValidationError(u'Unsupported file type.')

前の例をこれに組み込むこともできます-たとえば、拡張機能/アップロードされたタイプもチェックします(これはマジックよりもプライマリチェックとして高速である可能性があります)。これはまだ絶対確実ではありません-しかし、データに依存するため、より良いですinブラウザが提供するヘッダーではなく、ファイル。

注:これは、FileFieldモデルのバリデーターのリストに追加するバリデーター関数です。

3
chander