Как загрузить файлы с Django

В этом руководстве вы узнаете о принципах загрузки файлов Django и о том, как обрабатывать загрузку файлов с использованием форм моделей. В конце этого поста вы найдете исходный код примеров, которые я использовал, чтобы вы могли попробовать и изучить.

Также не забудьте ознакомиться с документацией Django по загрузке файлов.

Основы загрузки файлов с Django

Когда файлы передаются на сервер, данные файла в конечном итоге помещаются в request.FILES.

Для формы HTML обязательно должен быть правильно установлен атрибут enctype="multipart/form-data". В противном случае request.FILES будет пустым.

Форма должна быть отправлена методом POST.

У Django есть подходящие поля модели для обработки загруженных файлов: FileField и ImageField.

Файлы, загруженные в FileField или ImageField, хранятся не в базе данных, а в файловой системе.

FileField и ImageField создаются как строковое поле в базе данных (обычно VARCHAR), содержащее ссылку на фактический файл.

Если вы удалите экземпляр модели, содержащий FileField или ImageField, Django не удалит физический файл, а только ссылку на файл.

Аргумент request.FILES является словарным объектом. Каждый ключ в request.FILES - это имя из <input type="file" name="" />.

Каждое значение в request.FILES является экземпляром UploadedFile.

Вам нужно будет установить MEDIA_URL и MEDIA_ROOT в файле settings.py вашего проекта.

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

На сервере разработки вы можете обслуживать загруженные пользователем файлы (мультимедиа), используя представление django.contrib.staticfiles.views.serve().

from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    # Project url patterns...
]

if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Чтобы получить доступ к MEDIA_URL в шаблоне, вы должны добавить django.template.context_processors.media к вашим context_processors в конфигурации TEMPLATES.

Простая загрузка файла

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

simple_upload.html

{% extends 'base.html' %}

{% load static %}

{% block content %}
  <form method="post" enctype="multipart/form-data">
    {% csrf_token %}
    <input type="file" name="myfile">
    <button type="submit">Upload</button>
  </form>

  {% if uploaded_file_url %}
    <p>File uploaded at: <a href="{{ uploaded_file_url }}">{{ uploaded_file_url }}</a></p>
  {% endif %}

  <p><a href="{% url 'home' %}">Return to home</a></p>
{% endblock %}

views.py

from django.shortcuts import render
from django.conf import settings
from django.core.files.storage import FileSystemStorage

def simple_upload(request):
    if request.method == 'POST' and request.FILES['myfile']:
        myfile = request.FILES['myfile']
        fs = FileSystemStorage()
        filename = fs.save(myfile.name, myfile)
        uploaded_file_url = fs.url(filename)
        return render(request, 'core/simple_upload.html', {
            'uploaded_file_url': uploaded_file_url
        })
    return render(request, 'core/simple_upload.html')

Загрузка файла с модельными формами

Это более удобный способ. Формы моделей выполняют валидацию, автоматически строят абсолютный путь для загрузки, обрабатывают конфликты имен файлов и другие распространенные задачи.

models.py

from django.db import models

class Document(models.Model):
    description = models.CharField(max_length=255, blank=True)
    document = models.FileField(upload_to='documents/')
    uploaded_at = models.DateTimeField(auto_now_add=True)

forms.py

from django import forms
from uploads.core.models import Document

class DocumentForm(forms.ModelForm):
    class Meta:
        model = Document
        fields = ('description', 'document', )

views.py

def model_form_upload(request):
    if request.method == 'POST':
        form = DocumentForm(request.POST, request.FILES)
        if form.is_valid():
            form.save()
            return redirect('home')
    else:
        form = DocumentForm()
    return render(request, 'core/model_form_upload.html', {
        'form': form
    })

model_form_upload.html

{% extends 'base.html' %}

{% block content %}
  <form method="post" enctype="multipart/form-data">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Upload</button>
  </form>

  <p><a href="{% url 'home' %}">Return to home</a></p>
{% endblock %}

О параметре FileField upload_to

Смотрите пример ниже:

document = models.FileField(upload_to='documents/')

Обратите внимание на параметр upload_to. Файлы будут автоматически загружены в MEDIA_ROOT/documents/.

Также возможно сделать что-то вроде:

document = models.FileField(upload_to='documents/%Y/%m/%d/')

Загруженный сегодня файл будет загружен в MEDIA_ROOT/documents/2019/08/01/.

upload_to также может быть вызываемым параметром, который возвращает строку. Этот вызываемый параметр принимает два параметра, экземпляр (instance) и имя файла (filename).

def user_directory_path(instance, filename):
    # file will be uploaded to MEDIA_ROOT/user_<id>/<filename>
    return 'user_{0}/{1}'.format(instance.user.id, filename)

class MyModel(models.Model):
    upload = models.FileField(upload_to=user_directory_path)

Скачать примеры

Код, используемый в этом посте, доступен на Github.

git clone https://github.com/sibtc/simple-file-upload.git
pip install django
python manage.py migrate
python manage.py runserver

Перевод статьи https://simpleisbetterthancomplex.com/tutorial/2016/08/01/how-to-upload-files-with-django.html

Вернуться на верх