Курс по Django: https://stepik.org/a/183363
Архив проекта: 50_sitewomen.zip
На данный момент
мы с вами умеем загружать произвольные файлы на сервер и сделали загрузку
изображений для наших постов. Давайте теперь настроим отображение изображения
при просмотре поста. Но сначала посмотрим, что из себя представляет поле photo.
Перейдем в
консоль фреймворка Django:
python manage.py shell_plus
И прочитаем из
таблицы women последнюю
запись:
w = Women.objects.all()[0]
У объекта w имеется атрибут photo:
который
ссылается на объект ImageFieldFile. Если после photo поставить точку
и нажать Tab, то увидим
множество атрибутов и методов этого объекта. В частности, нас будет
интересовать локальный атрибут url:
который
возвращает URL-адрес для
получения изображения с сервера. Давайте им воспользуемся и пропишем в шаблоне post.html следующие
строчки сразу после заголовка первого уровня:
{% if post.photo %}
<img class="img-article-left" src="{{post.photo.url}}"></p>
{% endif %}
Однако если
сейчас открыть последний пост, то увидим, что изображение для него не
загружается. И, действительно, открыв вкладу «Network» в браузере и
обновив страницу, видим статус 404 у изображения. Дело в том, что пока сервер
не может связать этот URL с физическим маршрутом к файлу изображения
на сервере. Для этого нам нужно сделать следующие действия. В файле
конфигурации settings.py пропишем еще
один параметр:
На что он влияет?
Если сейчас обновить страницу поста, то URL-маршрут к изображению
будет иметь этот префикс media. Зачем он нужен? Смотрите, благодаря
единому уникальному префиксу для всех подгружаемых медиа-файлов, мы можем в urls.py пакета
конфигурации определить для них маршрут выдачи этих файлов. Для этого пропишем
такие строчки:
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
То есть, мы
говорим, если веб-сервер работает в режиме отладки, то в список маршрутов нужно
добавить еще один с префиксом media и связать его с каталогом MEDIA_ROOT, где эти файлы
расположены. Только так в режиме отладки мы можем раздавать загруженные файлы. В
боевом режиме в этом нет необходимости, т.к. сервер уже будет иметь необходимые
настройки для связки маршрута с рабочим каталогом.
Обновляем
страницу и видим, что теперь все работает корректно.
Давайте по
аналогии сделаем отображение изображений в списке постов. Для этого перейдем в
шаблон index.html и перед
заголовком h2 пропишем
следующие строчки:
{% if p.photo %}
<p ><img class="img-article-left thumb" src="{{p.photo.url}}"></p>
{% endif %}
Переходим на
главную страницу, видим изображение в списке постов.
Отображение изображений в админ-панели
Следующим шагом
добавим отображение миниатюр изображений, связанных с нашими постами,
непосредственно в списке. Перейдем в файл women/admin.py и в классе WomenAdmin
в списках fields и list_display укажем
поле photo:
fields = ['title', 'slug', 'content', 'photo', 'cat', 'husband', 'tags']
list_display = ('title', 'photo', 'time_create', 'is_published', 'cat')
А поле brief_info
я удалю.
Переходим в
админ-панель:
http://127.0.0.1:8000/admin/
и в списке
женщин в поле photo отображается
путь к изображению. Но мы бы хотели здесь видеть именно изображение, а не путь
к нему. Для этого сформируем новое вычисляемое поле, по аналогии с полем brief_info.
Переименуем метод brief_info в post_photo и возвратим
строку в виде тега img:
@admin.display(description="Изображение")
def post_photo(self, women: Women):
return mark_safe(f"<img src='{women.photo.url}' width=50>")
Здесь функция mark_safe() используется
для того, чтобы теги не экранировались и отрабатывали как HTML-теги. Осталось
в список list_display вместо photo указать post_photo:
list_display = ('title', 'post_photo', 'time_create', 'is_published', 'cat')
Если сейчас
обновить список в админ-панели, то увидим ошибку. Она связана с тем, что не у
всех постов имеются изображения. Поэтому нужно прописать следующую проверку:
@admin.display(description="Изображение")
def post_photo(self, women: Women):
if women.photo:
return mark_safe(f"<img src='{women.photo.url}' width=50>")
return "Без фото"
Теперь никаких
ошибок нет, все работает как требуется.
Мало того, мы
прямо здесь в админ-панели можем теперь редактировать посты и назначать им
изображения. Все будет работать. Также можно сделать отображение миниатюры
непосредственно при изменении статьи. Для этого достаточно указать ссылку на
наш метод post_photo() в атрибутах:
@admin.register(Women)
class WomenAdmin(admin.ModelAdmin):
fields = ['title', 'slug', 'content', 'photo', 'post_photo', 'cat', 'husband', 'tags']
readonly_fields = ['post_photo']
...
Все, теперь мы
видим изображение загруженной фотографии в форме редактирования.
Чтобы узнать о
других возможностях настройки формы редактирования, на странице документации
можно посмотреть список атрибутов для класса ModelAdmin. В частности,
установка вот такого атрибута:
добавляет
верхнюю панель для управления записью, что бывает очень удобно.
Курс по Django: https://stepik.org/a/183363