Курс по Django: https://stepik.org/a/183363
Архив проекта: 49_sitewomen.zip
На прошлом
занятии мы с вами научились загружать произвольные и графические файлы на
сервер. Но как воспользоваться этими файлами, если отсутствует информация: кто
их загружал, для чего загружал, какое имя файла в итоге было сгенерировано и
т.п. Поэтому, чаще всего, загрузка происходит в связке с моделями, то есть, с таблицами
БД. Давайте подробно разберемся, как это работает.
Для простоты
вначале определим модель новой таблицы, в которой будут храниться ссылки на
загруженные файлы. Пусть она будет следующей (в файле women/models.py):
class UploadFiles(models.Model):
file = models.FileField(upload_to='uploads_model')
Здесь фигурирует
уже знакомый нам класс FileField, но взятый уже из ветки models. Поэтому это
несколько иной класс и у него имеется дополнительный параметр upload_to – каталог, в
который будет происходить загрузка файлов.
После
определения новой модели нам нужно создать и применить миграции:
python manage.py makemigrations
python manage.py
migrate
В БД появляется
новая таблица и мы сейчас напрямую воспользуемся нашей моделью для сохранения
файла на сервер. Для этого перейдем в файл women/views.py и найдем
функцию about(). В ней после
проверки корректности переданных данных, создадим объект класса модели UploadFiles с последующим
вызовом метода save():
def about(request):
if request.method == "POST":
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
# handle_uploaded_file(form.cleaned_data['file'])
fp = UploadFiles(file=form.cleaned_data['file'])
fp.save()
else:
form = UploadFileForm()
return render(request, 'women/about.html', {'title': 'О сайте', 'menu': menu, 'form': form})
Давайте
посмотрим, как это будет работать. Выберем файл, нажмем «Отправить» и у нас
автоматически был создан каталог uploads_model и в нем
размещен загруженный файл. А в таблице БД появилась запись с путем к этому
файлу. Мало того, если мы попробуем еще раз загрузить тот же файл, то никаких
коллизий не возникнет и ему автоматически будет присвоено другое имя.
Соответственно, в таблице видим еще одну запись.
Вот так
фреймворк Django позволяет
автоматизировать процесс загрузки файлов на сервер. Функция handle_uploaded_file()
нам теперь не нужна и ее можно удалить.
Осталось сделать
один важный штрих. Мы можем на уровне всего проекта указать единую папку, в
которую будут сохраняться все загружаемые файлы. Это делается в файле settings.py пакета
конфигурации, в котором можно определить следующую переменную:
MEDIA_ROOT = BASE_DIR / 'media'
Теперь все файлы
будут загружаться в каталог media, создавая в нем подкаталоги. Проверим
это. Удалим все папки uploads, перезапустим веб-сервер и снова
загрузим файл. У нас автоматически был сформирован каталог media, в нем
подкаталог uploads_model, указанный в
параметре upload_to='uploads_model' класса модели и в этом подкаталоге размещен
выбранный файл. В таблице видим очередную запись с этой последней загрузкой.
Вот так легко и просто производится сохранение произвольных данных на сервер с
использованием классов моделей.
Добавление изображений к постам
Пока мы с вами
использовали обычную форму для загрузки файлов. Однако совместно с моделями
было бы логично применять формы в связке с ними, то есть, класс ModelForm. Давайте это
сделаем.
У нас уже есть
форма добавления поста по известным женщинам, которая базируется на модели Women. Поэтому, я
просто добавлю в эту модель еще одно поле photo следующим
образом:
photo = models.ImageField(upload_to="photos/%Y/%m/%d/", default=None, blank=True, null=True, verbose_name="Фото")
Мы здесь
используем уже знакомый нам класс ImageField с параметром upload_to, который
определяет путь загрузки для изображений. Обратите внимание, как он определен.
Здесь на место спецификаторов %Y, %m, %d будут
подставлены текущий год (четыре цифры), текущий месяц и текущий день. Это позволит
нам при массовой загрузке изображений, разнести их по отдельным подкаталогам.
После изменения
модели создадим и выполним миграции:
python
manage.py makemigrations
python manage.py
migrate
Далее, перейдем
в шаблон addpage.html. Здесь в тег
формы необходимо добавить параметр:
enctype="multipart/form-data"
Иначе связанные
данные не будут отправляться браузером на сервер.
В файле women/forms.py в классе AddPostForm
укажем поле photo в коллекции fields:
fields = ['title', 'slug', 'content', 'photo', 'is_published', 'cat', 'husband', 'tags']
А в файле women/views.py в функции addpage() при создании модели
AddPostForm по ветке POST укажем второй параметр rquest.FILES:
def addpage(request):
if request.method == 'POST':
form = AddPostForm(request.POST, request.FILES)
if form.is_valid():
# print(form.cleaned_data)
form.save()
return redirect('home')
else:
form = AddPostForm()
return render(request, 'women/addpage.html', {'menu': menu, 'title': 'Добавление статьи', 'form': form})
Теперь все готово,
запускаем веб-сервер, переходим на страницу добавления поста:
http://127.0.0.1:8000/addpage/
и в форме видим
отображение поля для загрузки файла изображения. Давайте создадим какой-нибудь
новый пост вместе с изображением:
Рианна; rianna; Биография
Рианны; Певицы
На сервере в
рабочем каталоге появился папка media с набором подкаталогов и загруженным
файлом изображения. В таблице women видим новую запись с заполненным полем photo.
Все, мы с вами
организовали загрузку изображения для поста и связали его с конкретной записью
с помощью дополнительного поля photo. На следующем занятии мы сделаем
очередной шаг и посмотрим, как можно отображать ранее загруженные изображения
на HTML-странице.
Курс по Django: https://stepik.org/a/183363