Как ограничить типы файлов при загрузке файлов для ModelForms с помощью FileFields?

Моя цель - ограничить FileField в Django ModelForm для PDF файлов и документов Word. Ответы, с которыми я столкнулся, касаются создания отдельного обработчика файлов, но я не уверен, как это сделать в контексте ModelForm. Есть ли параметр в settings.py, который я могу использовать для ограничения типов файлов загрузки?

Ответ 1

Я обрабатываю это, используя метод clean_ [your_field] в ModelForm. Вы можете установить список допустимых расширений файлов в settings.py для проверки в своем чистом методе, но нет ничего встроенного в settings.py для ограничения типов загрузки.

Django-Filebrowser, например, использует подход к созданию списка допустимых расширений файлов в settings.py.

Надеюсь, что это поможет тебе.

Ответ 2

Создайте метод проверки, например:

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])

Кроме того, вместо того, чтобы вручную устанавливать расширения, которые позволяет ваша модель, вы должны создать список на свой файл settings.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!')

Ответ 3

Проверка с расширением имени файла не является последовательным способом. Например, я могу переименовать 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])

Ответ 4

Для более общего использования я написал небольшой класс ExtensionValidator, который расширяет встроенный Django 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

Более простой способ сделать это, как показано ниже в вашей форме

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

Ответ 6

Я использую что-то в этих строках (обратите внимание: для этого требуется "pip install filemagic" ):

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.')

Возможно, вы также можете включить в него предыдущие примеры - например, также проверьте тип добавочного/загруженного (который может быть быстрее, чем первичная проверка, чем магия). Это все еще не является надежным - но это лучше, поскольку оно полагается больше о данных в файле, а не о браузерах.

Примечание. Это функция валидатора, которую вы хотите добавить в список валидаторов для модели FileField.