Когда вы создаете форму в HTML, она имеет определенную кодировку (или метод отправки данных на сервер).По умолчанию используется кодировка application/x-www-form-urlencoded
, которая по существу отправляет сведения о форме в одной строке.Однако, если вы хотите загрузить файлы на сервер, вам нужно установить кодировку на multipart/form-data
(это строка enctype="..."
, которую вы заметите во всех руководствах по этой теме).Это отправляет данные в несколько частей, по одной на поле формы.Для примера того, как выглядят эти две кодировки, см. Здесь .
Когда Django встречает кодировку multipart/form-data
, он разбивает полученные данные на два словаря: словарь request.FILES
содержит любойзагруженные файлы, в то время как request.POST
содержит любые другие поля формы.Если вам интересно, обработка выполняется классом MultiPartParser
в файле django/http/__init__.py
.
Чтобы проиллюстрировать, как эти данные возвращаются в ваш код, давайте создадим простое приложение.Во-первых, давайте создадим простую форму, состоящую из символьного поля и поля файла:
from django import forms
class TestForm(forms.Form):
name = forms.CharField()
file = forms.FileField()
Далее, мы создадим простое представление для создания формы, привязки к ней любых отправленных данных и их рендеринга.через шаблон:
from django.shortcuts import render_to_response
from django.template import RequestContext
from forms import TestForm
def show_form(request):
if request.method == 'POST':
form = TestForm(request.POST, request.FILES)
else:
form = TestForm()
context = {
'form': form
}
return render_to_response('show_form.html', context, RequestContext(request))
И, наконец, мы будем использовать шаблон для отображения формы и некоторой информации как о запросе, так и о форме:
<html>
<head>
<title>Django forms - file test</title>
</head>
<body>
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" />
</form>
<h2>Request details</h2>
<p>
Request method: {{ request.method }}
<br />
POST data: {{ request.POST|default:"No data" }}
<br />
FILES data: {{ request.FILES|default:"No data" }}
</p>
<h2>Form details</h2>
<p>
Cleaned data: {{ form.cleaned_data|default:"No data" }}
</p>
</body>
</html>
Обратите внимание, что вы 'Вам нужно будет включить контекстный процессор django.core.context_processors.request
в ваших настройках, чтобы увидеть подробности о запросе.
Если мы затем запустим сервер и направим наш браузер на просмотр, мы увидимто, что мы ожидали увидеть - пустая форма, режим запроса был GET, и не было POST, FILES или данных формы.
Далее, введите имя в поле символа, но не выбирайтефайл для загрузки.После отправки мы получаем ожидаемую ошибку об обязательном заполнении поля файла.Для нас более интересна информация о запросе:
Детали запроса
Метод запроса: POST
Данные POST:
Данные ФАЙЛОВ: Нет данных
Детали формы
Очищенные данные: Нет данных
Поскольку информация о файлах не была отправлена браузером, Django добавилвсе детали формы в словаре POST и оставил словарь FILES пустым.Поскольку форма недействительна, с ней не связано никаких данных.
Теперь давайте попробуем использовать ее без имени, но с файлом для загрузки:
Запросить информацию
Метод запроса: POST
Данные POST:
ФАЙЛЫ:]}>
Сведения о форме
Очищенные данные: нет данных
Теперь отправленные данные разделены между словарями POST и FILES.К файлу можно получить доступ через request.FILES['file']
, но не через данные, очищенные от форм, так как форма была признана недействительной из-за отсутствия имени.Поскольку загруженный мною файл был небольшим, он хранится в памяти;файлы выше определенного размера (по умолчанию 2,5 МБ) будут храниться во временном каталоге, но ваш код может обрабатывать их одинаково.
Наконец, давайте попробуем сделать это со значениями для обоих полей:
Детали запроса
Способ запроса: POSTДанные POST:ФАЙЛЫ данные:]}>
Сведения о форме
Чистые данные: {'name': u'Blair ',' file ':}
Поскольку данные действительны и привязаны к форме, к файлу также можно получить доступ через cleaned_data
формы.
Потенциальная выгода от доступа к нему через request.FILES
: если форма недействительна, вы все равно можете сохранить файл где-нибудь, прежде чем попросить пользователя исправить данные.Это предотвращает необходимость повторной загрузки файла (что может быть довольно затратным с точки зрения времени и пропускной способности, если вы работаете с большими файлами).Если вы хотите работать только с небольшими файлами, это не будет иметь большого значения, но, вероятно, лучше использовать request.FILES
.Так же поступает документация по загрузке файлов Django .