Подключение статических файлов

Курс по Django: https://stepik.org/a/183363

Архив проекта: 15_sitewomen.zip

На предыдущем занятии мы в целом познакомились с шаблонами в Django. Продолжим эту тему и следующий важный шаг – научиться подключать к шаблонам статические файлы, например, оформление CSS, JavaScript, изображения и так далее. Здесь есть свои тонкости. Как мы помним, наш проект может работать в двух режимах: отладки – на тестовом веб-сервере; эксплуатации – на реальном веб-сервере. Так вот, в режиме отладки статические файлы Django ищет во всех подкаталогах static приложений, которые прописаны в коллекции INSTALLED_APPS. То есть, статические файлы при отладке совершенно спокойно можно размещать в подкаталоге static нашего приложения. Но, в режиме эксплуатации реальный веб-сервер будет брать все статические файлы из папки static, расположенной, как правило, в каталоге всего проекта. И здесь возникает вопрос, как перенести все файлы из разных папок static приложений в единый каталог static всего проекта? Для этого, при подготовке сайта к эксплуатации, выполняется специальная команда фреймворка Django:

python manage.py collectstatic

которая собирает все статические файлы из разных приложений и модулей и помещает в одну общую папку проекта.

Так вот, чтобы корректно работал весь этот механизм, в пакете конфигурации необходимо определить три константы:

  • STATIC_URL – префикс URL-адреса для статических файлов;
  • STATIC_ROOT – путь к общей статической папке, формируемой при запуске команды collectstatic (для сбора всей статики в единый каталог при размещении сайта на реальном веб-сервере);
  • STATICFILES_DIRS – список дополнительных (нестандартных) путей к статическим файлам, используемых для сбора и для режима отладки.

По умолчанию, при создании проекта, Django автоматически формирует только одну переменную STATIC_URL. Две другие пока добавлять не будем. Кроме того, в списке INSTALLED_APPS обязательно должна присутствовать строчка:

'django.contrib.staticfiles',

Если ее по каким-то причинам нет, то следует добавить, иначе статические файлы в шаблонах подключаться не будут.

Давайте теперь создадим папку static в нашем приложении women и, также как и для шаблонов, укажем в ней вложенный каталог women, чтобы не было конфликтов имен между статическими файлами разных приложений. (В действительности, Django просто найдет первый подходящий файл и на этом остановится. Чтобы этот файл был тем, что нам нужен, как раз и используется дополнительный каталог, который играет роль некоторого пространства имен.)

В этом последнем подкаталоге уже будем размещать файлы css – для файлов CSS; js – для файлов JavaScript; images – для общих файлов изображений и так далее. Я создам подкаталог css для файла стилей нашего сайта. И в нем размещу файл styles.css, который заготовил заранее, чтобы не отвлекаться на CSS-оформление сайта, а сосредоточится на изучении фреймворка Django. Вы сможете скачать весь этот проект с github и, при необходимости, внимательно его изучить. Также создам подкаталог images и скопирую в него все необходимые изображения для базового оформления сайта.

Опять же, если вы не знакомы с CSS или HTML, то советую пройти ознакомительный курс по следующей ссылке:

https://www.youtube.com/playlist?list=PLA0M1Bcd0w8wRiyGX_9y-fUiBPi1vqaTb

Все, подготовительная часть завершена. Теперь мы можем использовать эти внешние файлы в шаблонах нашего приложения. Для этого используется специальный тег static, который сначала подключается в шаблоне (base.html):

{% load static %}

А, затем, для формирования URL к тому или иному статическому файлу, используется конструкция:

{% static ' <путь к файлу от папки static>' %}

Например, для подключения css-файла в базовом шаблоне base.html, следует прописать:

<link type="text/css" href="{% static 'women/css/styles.css' %}" rel="stylesheet" />

При просмотре страницы увидим следующий URL-адрес:

<link type="text/css" href="/static/women/css/styles.css" rel="stylesheet" />

И, щелкнув по нему, убеждаемся, что он успешно загружается.

Отлично, это мы сделали. Далее, я возьму заготовленные html-файлы для базового шаблона страниц (base.html) и главной страницы (index.html). Для более детального ознакомления вы сможете их скачать по ссылке с github.

Конечно, вы можете использовать свои шаблоны, принципиального значения это не будет иметь. Часто для оформления сайтов используют онлайн-сервисы. Наиболее известный из них

https://getbootstrap.com

Но я намеренно не стал к нему обращаться, чтобы не усложнять изложение материала по Django.

Итак, на нашем сайте выводится пока только заголовок и краткий контент статей. Я его увеличу для первой статьи следующим образом:

data_db = [
    {'id': 1, 'title': 'Анджелина Джоли', 'content': '''<h1>Анджелина Джоли</h1> (англ. Angelina Jolie[7], при рождении Войт (англ. Voight), ранее Джоли Питт (англ. Jolie Pitt); род. 4 июня 1975, Лос-Анджелес, Калифорния, США) — американская актриса кино, телевидения и озвучивания, кинорежиссёр, сценаристка, продюсер, фотомодель, посол доброй воли ООН.
 
Обладательница премии «Оскар», трёх премий «Золотой глобус» (первая актриса в истории, три года подряд выигравшая премию) и двух «Премий Гильдии киноактёров США».''', 'is_published': True},
    {'id': 2, 'title': 'Марго Робби', 'content': 'Биография Марго Робби', 'is_published': False},
    {'id': 3, 'title': 'Джулия Робертс', 'content': 'Биография Джулия Робертс', 'is_published': True},
]

И поставим задачу выводить не более 50 слов. Это можно сделать с помощью следующего фильтра:

{{p.content|truncatewords:50}}

Напомню, что подробную информацию по всем встроенным фильтрам фреймворка Django можно посмотреть по ссылке:

https://docs.djangoproject.com/en/4.2/ref/templates/builtins/

Содержимое выглядит уже лучше. Далее, мы сделаем так, чтобы каждая строка описания выводилась с новой строки в окне браузера. Для этого добавим еще один фильтр:

{{p.content|linebreaks|truncatewords:50}}

Наконец, сделаем так, чтобы теги внутри описания не экранировались, а применялись браузером для разметки текста. Для этого заключим содержимое контента в тег autoescape с параметром off:

{% autoescape off %}
{{p.content|linebreaks|truncatewords:50}}
{% endautoescape %}

Это еще один пример, как можно использовать различные теги и фильтры в шаблонах фреймворка Django.

После того, как мы настроили наше оформление сайта, давайте вернемся к параметрам STATIC_URL и STATICFILES_DIRS. Предположим, что мы размещаем статические файлы не в приложении, а в проекте. Для этого перенесем нашу папку static на уровень проекта. Если теперь перезапустить тестовый веб-сервер и обновить страницу в браузере комбинациями клавиш Ctrl+F5, то оформление пропадет. Это связано с тем, что фреймворк Django не находит каталог static, который теперь имеет нестандартное размещение. Но это легко поправить с помощью коллекции STATICFILES_DIRS:

STATICFILES_DIRS = [BASE_DIR / 'static']

Она позволяет для режима отладки задавать дополнительные нестандартные пути для поиска статических файлов. Теперь, при обновлении страницы мы снова увидим прежнее оформление.

Я верну папку static снова в приложение women и удалю список STATICFILES_DIRS, так как все пути у нас стандартные.

Замечания по запуску веб-сервера в режиме DEBUG=False

Если мы сейчас попробуем запустить веб-сервер не в режиме отладки с параметром:

DEBUG = False

то при обновлении главной страницы сайта все оформление пропадет. Но это лишь особенность работы тестового веб-сервера. В этом случае его нужно запустить с параметром --insecure следующей командой:

python manage.py runserver --insecure

Теперь, все снова работает, как и прежде. То есть, если вам понадобится на локальном компьютере протестировать работу сайта без отладки и с возможностью загрузки статических файлов, то применяйте параметр --insecure.

В дальнейшем, на реальном веб-сервере, все статические файлы собираются в единый каталог, как правило, с именем static с помощью команды:

python manage.py collectstatic

и, затем, берутся из этой папки.

Курс по Django: https://stepik.org/a/183363

Видео по теме