Django 5 для начинающих

Прогресс по курсу:  9/1004

2.7 Шаблоны, часть 2.
4 из 16 шагов пройдено
0 из 56 баллов  получено

Статичные файлы

Пришло время ближе познакомиться со статическими файлами. Статическими файлами называются все файлы каскадных таблиц стилей (Cascading Style Sheets, CSS), изображений, а также скриптов JavaScript, - т. е. файлы, которые не изменяются динамически и содержание которых не зависит от контекста запроса и одинаково для всех пользователей. Также в качестве статичных файлов не редко используют HTML файлы, такие как шапка сайта, футер, и другие.

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

В частности, в файле settings.py определена переменная STATIC_URL, которая хранит путь к каталогу со статическими файлами:

STATIC_URL = 'static/'

А среди установленных приложений в переменной INSTALLED_APPS указано приложение django.contrib.staticfiles:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'blog'
]

Чтобы использовать статичные файлы в шаблоне, для этого в начале файла шаблона необходимо добавить:

{% load static %}

При этом данный код должен идти вверху нашего шаблона, перед <!DOCTYPE html> тегом.

Для определения пути к статическим файлам используются выражения такого типа:

{% static "путь к файлу внутри папки static" %}

Создадим папку static в папке приложения blog. Внутри еще одну папку images, и добавим туда изображение. В результате получится следующая структура:

И вот так это используется в шаблоне:

{% load static %}
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Учу Django</title>
</head>
<body>
    <h1>Логотип Django</h1>
    <img src="{% static 'images/django_logo.png' %}" width="300px">
</body>
</html>

И если мы откроем наш сайт, то увидим следующее:

 

Настройка путей к файлам

Если нас не устраивает хранение файлов в каталоге по умолчанию - каталоге static приложения, либо мы хотим указать несколько папок, то мы можем в файле settings.py задать все необходимые каталоги с помощью переменной STATICFILES_DIRS, которая принимает список путей:

STATICFILES_DIRS = [
    BASE_DIR / "static",
    "/var/www/static/",
    "/somefolder/"
]

 

TemplateView

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

Можно воспользоваться встроенным классом TemplateView:

from django.urls import path
from django.views.generic import TemplateView
from blog import views

urlpatterns = [
    path('', views.index),
    path('about/', TemplateView.as_view(template_name="blog/about.html")),
    path('contact/',TemplateView.as_view(template_name="blog/contact.html")),
]

То есть в данном случае за вызов шаблона главной страницы у нас будет отвечать функция views.index в views.py, а шаблоны разделов about и contact мы определили в самом файле urls.py

Стоит отметить, что в пути к шаблону страницы также может указываться и папка, в которой он находится. В нашем случае шаблоны находятся в корне папки templates. Например если наш шаблон находится в папке templates/blog/about.html, то и путь мы должны указать как blog/about.html.

Также с помощью параметра extra_context в метод as_view можно передать данные для их отображения в шаблоне. Данные должны представлять собой словарь. В качестве примера передадим в шаблон about.html виды работ, которые выполняет компания.

Для этого используем переменную header и следующим образом изменим код файла urls.py:

from django.urls import path
from django.views.generic import TemplateView
from blog import views

urlpatterns = [
    path('', views.index),
    path("about/", TemplateView.as_view(template_name="blog/about.html", extra_context={"header": "О сайте"})),
    path('contact/', TemplateView.as_view(template_name="blog/contact.html")),
]


Теперь мы можем добавить в наш шаблон переменную {{ header }} что выведет её содержимое. Создадим файл about.html в папке templates/blog/ следующего содержания:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Учу Django</title>
</head>
<body>
    <h1>{{ header }}</h1>
</body>
</html>


Теперь перейдем по адресу http://127.0.0.1:8000/about/, и мы увидим что данные передались:


  • Комментариев
Будьте вежливы и соблюдайте наши принципы сообщества. Пожалуйста, не оставляйте решения и подсказки в комментариях, для этого есть отдельный форум.
Оставить комментарий
Комментарий закреплён

Понравилась задача, тест или урок? Поставьте лайк, поддержите курс. Ваша поддержка очень важна для нас.

Вопрос по структуре проекта. В предыдущем разделе про шаблоны было сказано что лучше создавать отдельную папку temlate в корне проекта и уже в ней создавать разбивку по одноименным папкам для каждого приложения. Предполагаю, что это сделано потому, что одними и теми же шаблонами могут пользоваться разные приложения через расширение шаблонов и т.д. А в этом разделе по статическим файлам, предлагается создавать папку static  непосредственно в папке приложения. Предполагаю, что для каждого приложения обычно идут свои мало повторяющиеся статические файлы, поэтому нет смысла объединять их все в одной папке в корне проекта. Подскажите пожалуйста, я правильно рассуждаю, или есть какие-то другие причины для такой структуры папок в проекте? Судя по скрину из степа 2.3.5 там есть отдельная папка static в корне проекта. Как по правильному надо делать в реальном проекте? Как делается в промышленной разработке?

@Максим_Михеев, Вы правильно рассуждаете. Вообще в документации Django написано хранить статические файлы в папке приложения. (blog/static/), но при этом четко написано, что можно хранить статику "где угодно". В мелких проектах можно хранить внутри приложения, в крупных проектах удобнее в корне проекта. Тут самый главный фактор, это как будет удобнее это обслуживать, если в мелком проекте 1 файл стилей, то это одно, а если там css, js, и куча всяких изображений, то это уже другое.

Изменен Илья Перминов

@Максим_Михеев, Понял, спасибо за подробный ответ.

Каким образом в ваших примерах начали корректно обрабатываться содержащиеся в папке blog/static/images изображения?

Мне пришлось добавить эту папку явно в settings.py:

Без этого картинка не отображалась

@ilya_kutaev, Пришлите полный скрин ваших папок проекта.

@Илья_Перминов, Спасибо! Не уверен, поможет ли - я шел по курсу дальше и менял их содержимое.

Вместо blog я назвал приложение app1, чтобы видеть, что нужно менять "руками" при копировании скриптов из уроков, и заодно потренироваться

Папку static на верхнем уровне создал, т.к. test выдавал предупреждение, что ее нет

Да, и у меня установилась Django 5, я начал проходить курс на следующий день после ее выхода - возможно, это нужно принимать во внимание

Изменен ilya kutaev

@ilya_kutaev, там опечатка, смотрите комментарий выше

@Никитин_Даниил, Непонятно, к чему это замечание, у вас там про очередность. {% load static %}  и <!DOCTYPE html>
У меня с этим вопросов не возникает, все работает в указанной в уроке очередности

@Илья_Перминов, Сконфигурировал все с самого начала, теперь работает, как полагается, статические файлы находятся и в папке static проекта, и приложения. При этом в settings.py я удалил все из STATICFILES_DIRS = []

Я на двух разных ПК прохожу курс, возможно, на одном что-то сбилось в настройках, "потерялось" приложение в INSTALLED_APPS.

Короче, чем меньше "лишних" настроек, тем все стабильнее работает - по крайней мере, на начальном этапе лучше ничего не менять.

Изменен ilya kutaev

@ilya_kutaev, тоже столкнулся с этой проблемой, спасибо, ваш коммент помог)

Опечатка:

@Максим_Михеев, Спасибо, поправил.

Здесь вроде нет необходимости прописывать в коде {% load static %} ?

@Максим_Михеев, Спасибо, поправил.

Опечатка (нет закрывающей квадратной скобки):

@Максим_Михеев, Спасибо, поправил.

сделайте еще по FastAPI , крусов по нему очень мало

@Alex_A, Если честно, то на данный момент мы именно этим и занимаемся)

@Илья_Перминов, буду ждать с нетерпением))

{%load static%} идет внутри <!DOCTYPE html>, тогда все работает корректно  

@Никитин_Даниил, Если мы верим документации, то подключение статики через {% load static %} может производиться в любом месте кода, лишь бы до вызова самих статичных файлов. 

не работает load static

@Шамбер_Егор, я даже заново приложение создал, я думаю, что проблема может быть в директориях  

и то, что в шаблоне png, а у меня jpg, не влияет, я менял, проблема в том, что load static вообще не видится

у меня Proffesional Edition

@Шамбер_Егор, а то что в шаблоне django_logo.png, а у вас файл django.jpg?

@Илья_Перминов, поменял, всё равно не работает

<img src="{% static 'images/django.jpg' %}" width="300px">

@Шамбер_Егор, Загрузите архив проекта по ссылке - https://mega.nz/filerequest/rANtUqzWHQ4

И отпишитесь сюда, я посмотрю сразу.

@Илья_Перминов, загрузил

@Шамбер_Егор, А почему у вас файлы urls.py и views.py пустые? Я добавил в них код и все работает:

@Илья_Перминов, скиньте скрины пожалуйста  urls.py и views.py, в них изначально был код, просто он пропал, когда я создал приложение заново, очень вероятно код там был неправильным и спасибо вам за вашу помощь, у вас очень хороший курс

@Шамбер_Егор, В вашем случае в папке main_app файл urls.py:

from django.urls import path
from main_app import views

urlpatterns = [
    path('', views.index),
]

и view.py

from django.shortcuts import render


def index(request):
    return render(request, "main_app/index.html")

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

@Илья_Перминов, спасибо вам, теперь сервер запускается и всё отображается как надо, правда ошибки из html файла никуда не делись, но даже с ошибками всё вроде работает

@Шамбер_Егор, если не ошибаюсь, то вы второй учащийся, у которого пайчарм подсвечивает ошибку после лоад статик. Причину так и не получилось установить, но все будет работать.

@Илья_Перминов

да, Pycharm это подсвечивает. чтобы решить, достаточно поменять местами первые две строки.

!!! Вопрос по STATICFILES_DIRS
1. Такой переменной по умолчанию нет в settings.py, я правильно понимаю, что мы её должны в случае чего задать сами?
2. Что здесь означает BASE_DIR?
!!! Также при указании load static во 2 строке шаблона, а именно "<!DOCTYPE html>" выдаёт ошибку "Unexpected tokens", как с ней "бороться".
P.S. Но с этой "ошибкой" всё равно всё работает, просто бесит это красное подчёркивание и знак ошибки
!!! Также есть вопрос про директории статических файлов. Запутался немного уже в этом вопросе.
У меня по умолчанию стоит STATIC_URL = "static/" (что кстати означает эта настройка, я не понял), я создаю папку static в приложении, закидываю туда картинку и в общем делаю как показано здесь. Всё работает. А как джанго определил, что там у меня есть статические файлы (ну понятно, что я ему в шаблоне адрес к изображению указал, но тогда получается зачем мне  STATIC_URL и STATICFILES_DIRS, если и я сам путь в шаблоне указываю?)
Помогите разобраться

Изменен Александр Ёлшин

@Aleksandr_Yolshin

1. Да, должны добавить, есть ещё много настроек, их тоже необходимо вручную прописывать.

2. Это базовая директория проекта, она задаётся в начале файла настроек так BASE_DIR = Path(__file__).resolve().parent.parent.

В PyCharm Community Edition эту ошибку можно обойти так {{ '<' }}{{ '!DOCTYPE html>' }}.

STATIC_URL = "static/" эта настройка задаёт в какой директории сайта будут доступны статичные файлы: например так https://127.0.0.1:8000/static/image.jpg.

STATICFILES_DIRS задаёт директории физического расположения статичных файлов.

Изменен Дмитрий Селезнев