Основы веб-разработки на Django

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

1. Введение в Django: установка, создание проекта и архитектура MVT

Введение в Django: установка, создание проекта и архитектура MVT

Добро пожаловать в курс «Основы веб-разработки на Django». Если вы читаете эту статью, значит, вы решили освоить один из самых мощных, популярных и востребованных веб-фреймворков в мире Python. Django используется такими гигантами, как Instagram, Pinterest, Mozilla и National Geographic. Но почему он так популярен?

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

Что такое Django и философия «Batteries Included»

Django — это высокоуровневый веб-фреймворк на языке Python, который поощряет быструю разработку и чистый, прагматичный дизайн. Он был создан разработчиками новостного издания в Канзасе (Lawrence Journal-World) для того, чтобы успевать публиковать новости в сжатые сроки. Отсюда и главный слоган: «Веб-фреймворк для перфекционистов с дедлайнами».

Одной из ключевых особенностей Django является принцип «Batteries Included» (Батарейки в комплекте). Это означает, что «из коробки» вы получаете множество инструментов, которые в других фреймворках пришлось бы искать и настраивать отдельно:

* ORM (Object-Relational Mapping): Позволяет работать с базой данных, используя код Python вместо SQL. * Административная панель: Готовый интерфейс для управления контентом. * Аутентификация: Система регистрации, входа и управления правами пользователей. * Маршрутизация URL: Гибкая система обработки адресов. * Безопасность: Защита от SQL-инъекций, XSS, CSRF и других атак.

Архитектура MVT: Model-View-Template

Большинство веб-фреймворков используют архитектуру MVC (Model-View-Controller). Django использует слегка измененную концепцию, которую называют MVT (Model-View-Template). Понимание этой структуры критически важно для дальнейшей работы.

Давайте разберем каждый компонент:

  • Model (Модель): Отвечает за данные. Это слой, который описывает структуру вашей базы данных. В Django модель — это класс Python, который превращается в таблицу базы данных. Вам не нужно писать SQL-запросы вручную; Django делает это за вас.
  • View (Представление): Это «мозг» вашего приложения. Вопреки названию, View в Django не отвечает за то, как выглядит страница (это делает Template). View отвечает за то, какие данные показать. Он получает запрос от пользователя, обращается к Модели за данными и передает их в Шаблон.
  • Template (Шаблон): Отвечает за внешний вид. Это HTML-файл с вкраплениями специального синтаксиса Django (Django Template Language), который позволяет выводить данные, переданные из View.
  • !Схема обработки запроса в архитектуре MVT

    Сравнение с MVC

    Часто возникает путаница в терминологии. Вот как MVT соотносится с классическим MVC:

    | Концепция MVC | Концепция Django (MVT) | Описание | | :--- | :--- | :--- | | Model | Model | Работа с данными и бизнес-логикой данных | | View | Template | Отображение данных (HTML) | | Controller | View | Обработка запроса и выбор того, что показать |

    В Django сам фреймворк берет на себя часть задач Контроллера (маршрутизацию запросов), оставляя разработчику написание логики во View.

    Подготовка окружения

    Перед тем как писать код, необходимо подготовить почву. Мы будем использовать виртуальное окружение. Это изолированная папка, в которой будут храниться библиотеки именно для этого проекта. Это позволяет избежать конфликтов версий между разными проектами.

    Шаг 1: Установка Python

    Убедитесь, что у вас установлен Python версии 3.8 или выше. Проверить это можно командой в терминале:

    Шаг 2: Создание виртуального окружения

    Создайте папку для вашего проекта и перейдите в нее. Затем выполните команду для создания виртуального окружения (назовем его venv):

    Для Windows:

    Для macOS/Linux:

    Шаг 3: Активация виртуального окружения

    После создания окружения его нужно активировать. После активации перед строкой ввода в терминале появится надпись (venv).

    Для Windows:

    Для macOS/Linux:

    Шаг 4: Установка Django

    Теперь, находясь внутри изолированного окружения, установим Django с помощью пакетного менеджера pip:

    Создание первого проекта

    В терминологии Django есть четкое разделение между Проектом (Project) и Приложением (App).

    * Проект — это глобальная конфигурация вашего веб-сайта. Он может содержать несколько приложений. * Приложение — это модуль, выполняющий конкретную задачу (например, блог, форум, магазин).

    Инициализация проекта

    Для создания проекта используется утилита django-admin. Давайте назовем наш проект config (это распространенная практика, чтобы отделить настройки от приложений) или myproject. Для примера используем mysite.

    Выполните команду:

    > Обратите внимание на точку . в конце команды. Она говорит Django создать проект в текущей папке, а не создавать новую вложенную папку. Это делает структуру удобнее.

    Структура файлов

    После выполнения команды вы увидите следующие файлы:

    Разберем, за что отвечает каждый файл:

    * manage.py: Это утилита командной строки, с помощью которой вы будете взаимодействовать с проектом (запускать сервер, создавать миграции и т.д.). Она является оберткой над django-admin. * mysite/: Это пакет Python вашего проекта. * __init__.py: Пустой файл, который говорит Python, что эта директория является пакетом. * settings.py: Самый важный файл. Здесь хранятся все настройки: подключение к базе данных, список установленных приложений, настройки безопасности, языковые параметры. * urls.py: «Оглавление» вашего сайта. Здесь вы связываете URL-адреса (например, /about/) с конкретными View-функциями. * wsgi.py и asgi.py: Точки входа для веб-серверов при развертывании сайта в интернете (deploy). WSGI — старый стандарт, ASGI — новый, поддерживающий асинхронность.

    Запуск сервера разработки

    Django поставляется с легким веб-сервером для разработки, чтобы вы могли видеть результаты своей работы без настройки настоящего хостинга.

    Выполните команду:

    Если все прошло успешно, вы увидите вывод, похожий на этот:

    Теперь откройте браузер и перейдите по адресу http://127.0.0.1:8000/. Вы должны увидеть приветственную страницу Django с изображением ракеты. Это означает, что установка прошла успешно!

    !Приветственная страница Django после успешного запуска сервера

    Создание приложения (App)

    Как мы говорили ранее, проект состоит из приложений. Давайте создадим наше первое приложение, например, blog.

    Остановите сервер (нажмите Ctrl+C в терминале) и выполните:

    Появится новая папка blog со своей структурой:

    * models.py: Здесь мы будем описывать структуру данных. * views.py: Здесь будет логика обработки запросов. * admin.py: Настройки для админ-панели. * tests.py: Файл для написания тестов.

    Регистрация приложения

    Создать приложение недостаточно, нужно «рассказать» о нем проекту. Для этого откройте файл mysite/settings.py, найдите список INSTALLED_APPS и добавьте туда название вашего приложения:

    Теперь Django знает о существовании приложения blog и будет учитывать его модели и настройки.

    Заключение

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

    В следующей статье мы углубимся в работу с данными: научимся создавать модели, проводить миграции и работать с базой данных через Django ORM.

    2. Модели данных и ORM: проектирование базы данных и миграции

    Модели данных и ORM: проектирование базы данных и миграции

    Приветствую вас на второй лекции курса «Основы веб-разработки на Django». В предыдущей статье мы подготовили рабочее окружение, создали проект mysite и приложение blog. Однако наше приложение пока «пустое»: оно не умеет хранить информацию.

    Сегодня мы займемся буквой M в архитектуре MVT — Моделями (Models). Мы разберем, как Django работает с базами данных, что такое ORM, как описывать структуру данных на языке Python и как переносить эти описания в реальную базу данных с помощью миграций.

    Что такое база данных и зачем нужен ORM?

    Любой современный веб-сайт — это не просто набор статических страниц, а система, которая хранит и обрабатывает данные: пользователей, посты, комментарии, товары. Для хранения этой информации используются базы данных (БД). Самый распространенный язык для общения с базами данных — это SQL (Structured Query Language).

    Однако писать SQL-запросы вручную (например, SELECT * FROM blog_post WHERE id = 1) может быть утомительно, небезопасно и сложно для поддержки. Здесь на сцену выходит ORM.

    ORM (Object-Relational Mapping) — это технология, которая связывает (мапит) объекты в коде программы с таблицами в базе данных. Простыми словами, это «переводчик» между Python и SQL.

    !Визуализация того, как ORM преобразует классы Python в таблицы базы данных.

    Преимущества использования Django ORM:

  • Вы пишете на Python: Вам не нужно знать SQL, чтобы работать с данными.
  • Безопасность: Django автоматически защищает запросы от SQL-инъекций.
  • Переносимость: Вы можете сменить базу данных (например, с SQLite на PostgreSQL), изменив всего одну строчку в настройках, не переписывая код запросов.
  • Создание первой модели

    В Django Модель — это класс Python, который наследуется от django.db.models.Model. Каждый атрибут этого класса представляет собой поле в базе данных.

    Давайте создадим модель для хранения постов нашего блога. Откройте файл blog/models.py. Сейчас он почти пуст. Измените его содержимое следующим образом:

    Разбор кода модели

    Давайте детально разберем, что мы написали:

    * class Post(models.Model): — Мы объявляем объект Post, который является моделью Django. * models.CharField — Это поле для хранения текста ограниченной длины. Мы используем его для заголовка (title) и обязательно указываем max_length=200. * models.TextField — Это поле для текста неограниченной длины. Идеально подходит для содержания поста (text). * models.DateTimeField — Поле для хранения даты и времени. * default=timezone.now означает, что при создании поста дата создания будет установлена автоматически на текущее время. * blank=True, null=True для published_date означает, что это поле может быть пустым (пост может быть создан, но еще не опубликован). * def __str__(self): — Это специальный метод Python (магический метод). Он говорит Django, что когда нужно отобразить этот объект как строку (например, в админ-панели), нужно вернуть его заголовок (self.title).

    Миграции: от кода к базе данных

    Мы написали код модели, но база данных об этом еще ничего не знает. В базе данных пока нет таблицы для наших постов. Чтобы синхронизировать наш код с базой данных, Django использует механизм миграций.

    Процесс состоит из двух шагов:

  • Создание миграции: Мы просим Django подготовить инструкции по созданию таблицы.
  • Применение миграции: Мы выполняем эти инструкции.
  • Шаг 1: Создание файла миграции

    Убедитесь, что ваше виртуальное окружение активировано, и вы находитесь в папке с файлом manage.py. Выполните команду:

    Вы должны увидеть сообщение:

    Django создал файл blog/migrations/0001_initial.py. Это и есть «чертеж» будущей таблицы.

    Шаг 2: Применение миграции

    Теперь применим этот чертеж к базе данных:

    Django выполнит SQL-команды, необходимые для создания таблицы. По умолчанию Django использует базу данных SQLite (файл db.sqlite3 в папке проекта), которая идеально подходит для разработки и не требует установки дополнительного софта.

    !Схематичное изображение двухэтапного процесса миграции: создание плана и его применение.

    Работа с данными через Django Shell

    Теперь, когда таблица создана, мы можем создавать, читать, обновлять и удалять записи (операции CRUD), используя Python. Для этого воспользуемся интерактивной консолью Django.

    Запустите консоль:

    Создание объектов

    Сначала импортируем нашу модель:

    Попробуем посмотреть все посты:

    Результат будет <QuerySet []>, что означает пустой список. Давайте создадим пост:

    Метод .save() сохраняет объект в базу данных. Теперь, если мы снова вызовем Post.objects.all(), мы увидим:

    Здесь сработал наш метод __str__, который мы определили ранее, вернув заголовок поста.

    Фильтрация объектов

    Django ORM позволяет легко искать данные. Например, найдем посты, где в заголовке есть слово "первый":

    Обратите внимание на двойное подчеркивание __ между title и contains. Это синтаксис Django для фильтрации полей.

    Регистрация модели в админ-панели

    Одной из киллер-фич Django является встроенная админка. Но по умолчанию наша новая модель там не видна. Нам нужно зарегистрировать её.

    Откройте файл blog/admin.py и приведите его к следующему виду:

    Теперь создадим суперпользователя (администратора), чтобы войти в систему:

    Следуйте инструкциям в терминале (введите имя, email и пароль). Пароль при вводе не будет отображаться — это нормально.

    Запустите сервер:

    Перейдите в браузере по адресу http://127.0.0.1:8000/admin/. После входа вы увидите раздел BLOG и таблицу Posts. Теперь вы можете создавать, редактировать и удалять посты через красивый графический интерфейс, не написав ни строчки HTML-кода для форм!

    Заключение

    Сегодня мы сделали огромный шаг вперед. Мы спроектировали структуру данных нашего приложения, научились превращать классы Python в таблицы базы данных с помощью миграций и освоили базовые операции с данными через ORM и админ-панель.

    В следующей статье мы свяжем наши данные с пользовательским интерфейсом: научимся создавать Views (Представления) и Templates (Шаблоны), чтобы отображать наши посты на реальных веб-страницах, доступных обычным пользователям.

    3. Маршрутизация и представления: обработка HTTP-запросов и URL-адреса

    Маршрутизация и представления: обработка HTTP-запросов и URL-адреса

    Добро пожаловать на третью лекцию курса «Основы веб-разработки на Django». В предыдущих статьях мы заложили фундамент: настроили окружение, создали проект и спроектировали базу данных с помощью Моделей (Model). Но пока что наш сайт — это «вещь в себе». У нас есть данные, но пользователи не могут их увидеть.

    Сегодня мы оживим наш проект. Мы разберем букву V (View) в архитектуре MVT и свяжем её с системой маршрутизации URL. Вы узнаете, что происходит с момента, когда пользователь вводит адрес в браузере, до момента, когда он видит ответ на экране.

    Жизненный цикл HTTP-запроса в Django

    Прежде чем писать код, важно понять, как Django обрабатывает входящие запросы. Интернет работает по протоколу HTTP (HyperText Transfer Protocol), который основан на принципе «запрос-ответ».

    Когда вы вводите адрес сайта (например, mysite.com/blog/) и нажимаете Enter, ваш браузер отправляет HTTP-запрос (Request) на сервер. Задача Django — принять этот запрос, понять, что именно хочет пользователь, и отправить обратно HTTP-ответ (Response).

    Этот процесс можно разбить на три ключевых этапа:

  • URL Dispatcher (Маршрутизатор): Django смотрит на запрошенный адрес (/blog/) и ищет соответствующее правило в файле urls.py.
  • View (Представление): Если правило найдено, Django вызывает связанную с ним Python-функцию (View). Эта функция выполняет логику: например, достает данные из базы.
  • Response (Ответ): Функция View возвращает данные браузеру (обычно в виде HTML-страницы).
  • !Схематичное изображение потока данных: от браузера через URL и View к пользователю.

    Настройка URL: карта вашего сайта

    Файл urls.py — это оглавление вашего веб-проекта. Именно здесь мы говорим Django: «Если пользователь зашел на страницу /about/, покажи ему функцию about_view».

    Глобальный urls.py

    В папке вашего проекта (mysite/urls.py) уже есть файл с маршрутами. Давайте посмотрим на него:

    Список urlpatterns — это сердце маршрутизации. Функция path() принимает два основных аргумента:

  • route (маршрут): Строка, содержащая URL-шаблон.
  • view (представление): Функция, которая будет вызвана.
  • Подключение URL приложения

    Хорошей практикой считается не писать все маршруты в одном файле, а разделять их по приложениям. У нас есть приложение blog. Давайте создадим для него свой файл маршрутов.

  • Создайте файл urls.py внутри папки blog/.
  • В главном файле mysite/urls.py подключите маршруты блога, используя функцию include.
  • Измените mysite/urls.py:

    Теперь, когда запрос приходит на главную страницу, Django передаст управление в blog/urls.py. Но этот файл пока пуст. Давайте наполним его.

    Создание Представлений (Views)

    View (Представление) — это обычная функция Python, которая принимает веб-запрос и возвращает веб-ответ. По соглашению, эти функции хранятся в файле views.py.

    Откройте blog/views.py. Сейчас там пусто. Давайте напишем простейшую функцию, которая выводит список постов.

    Разберем этот код: * Функция post_list принимает обязательный аргумент request. Это объект, содержащий всю информацию о запросе (IP-адрес пользователя, параметры браузера, данные формы и т.д.). * Функция возвращает объект HttpResponse. Это класс, который превращает строку текста в валидный HTTP-ответ.

    Теперь свяжем эту функцию с URL. Откройте созданный вами blog/urls.py и добавьте:

    Запустите сервер (python manage.py runserver) и зайдите на главную страницу http://127.0.0.1:8000/. Вы увидите текст: «Привет! Здесь будет список постов.».

    Связь с данными (Model + View)

    Выводить статический текст скучно. Давайте выведем реальные посты из базы данных, которые мы создали в прошлой лекции.

    Изменим blog/views.py:

    Теперь при обновлении страницы вы увидите заголовки ваших постов, разделенные вертикальной чертой. Мы успешно связали Модель и Представление!

    > Важно: В реальной разработке мы никогда не формируем HTML внутри Python-кода строками, как в примере выше. Для этого используются Шаблоны (Templates), которые мы изучим в следующей лекции. Сейчас мы используем строки только для демонстрации логики работы View.

    Динамические URL и передача параметров

    Представьте, что у вас в блоге 1000 статей. Вы не будете писать 1000 строк path для каждой статьи. Вам нужен один универсальный маршрут, который умеет обрабатывать разные ID постов.

    Django позволяет использовать конвертеры путей (path converters) для захвата части URL и передачи её в функцию View как аргумента.

    Синтаксис выглядит так: <тип_данных:имя_переменной>.

    Добавим новый маршрут в blog/urls.py:

    Разберем строку 'post/<int:pk>/': * post/ — статическая часть адреса. * <int:pk> — динамическая часть. Django ожидает здесь целое число (int) и передаст его в функцию view под именем pk (Primary Key).

    Теперь создадим функцию post_detail в blog/views.py:

    Если вы перейдете по адресу http://127.0.0.1:8000/post/5/, вы увидите: «Вы смотрите пост с номером 5».

    Обработка ошибок: 404 Not Found

    Что произойдет, если пользователь запросит пост с ID=999, которого нет в базе данных? Нам нужно корректно обработать эту ситуацию и вернуть ошибку 404 (Страница не найдена).

    Django предоставляет удобную функцию get_object_or_404. Она пытается получить объект из базы, а если его нет — автоматически вызывает ошибку 404.

    Обновим blog/views.py для полноценной работы:

    Теперь логика нашего приложения стала надежной:

  • Пользователь запрашивает /post/1/.
  • urls.py ловит число 1 и передает его в post_detail как pk=1.
  • post_detail ищет пост с таким ID в базе.
  • Если пост найден — возвращаем его данные.
  • Если поста нет — Django показывает страницу 404.
  • Именованные URL (Named URLs)

    Обратите внимание на аргумент name='post_list' в файле urls.py. Это имя маршрута.

    Давать маршрутам имена — критически важная практика. Это позволяет вам ссылаться на URL в коде не по жесткому адресу (который может измениться), а по его логическому имени. Если вы захотите переименовать адрес с /post/ на /article/, вам нужно будет изменить это только в одном месте — в urls.py, а все ссылки на сайте обновятся автоматически.

    Заключение

    Сегодня мы разобрали механизм маршрутизации и представлений. Теперь вы понимаете, как Django превращает URL-строку в вызов функции Python и как передавать параметры через адресную строку.

    Мы научились: * Настраивать urls.py и использовать include. * Создавать функции View, принимающие request. * Использовать динамические URL с конвертерами типов (<int:pk>). * Обрабатывать несуществующие объекты с помощью get_object_or_404.

    Однако наши ответы пока выглядят как простой текст. В следующей статье мы изучим Шаблоны (Templates) — последний элемент триады MVT, который позволит нам создавать красивые HTML-страницы и отделять дизайн от логики Python.

    4. Шаблоны и статика: создание пользовательского интерфейса и работа с CSS/JS

    Шаблоны и статика: создание пользовательского интерфейса и работа с CSS/JS

    Добро пожаловать на четвертую лекцию курса «Основы веб-разработки на Django». В предыдущих статьях мы проделали большой путь: настроили проект, спроектировали базу данных и научились обрабатывать URL-адреса, возвращая простые текстовые ответы из наших представлений (Views).

    Однако, если вы посмотрите на современные сайты, они не состоят из простого текста. Это сложные структуры с заголовками, картинками, меню, кнопками и стилями. В этой статье мы займемся последней буквой в аббревиатуре MVTTemplates (Шаблоны), а также научимся подключать статические файлы (CSS и изображения), чтобы наш блог выглядел профессионально.

    Зачем нужны шаблоны?

    В прошлой лекции мы возвращали HTML прямо из Python-кода:

    Этот подход имеет несколько критических недостатков:

  • Смешивание логики и дизайна: Python-разработчик не должен думать о верстке, а верстальщик не должен лезть в Python-код.
  • Нечитаемость: Представьте HTML-страницу на 1000 строк, записанную внутри одной Python-строки. Поддерживать такое невозможно.
  • Безопасность: Формирование HTML вручную открывает двери для XSS-атак (межсайтовый скриптинг).
  • Django решает эти проблемы с помощью системы шаблонов. Шаблон — это отдельный файл (обычно HTML), который содержит статику (каркас страницы) и специальный синтаксис для вставки динамических данных.

    Настройка и создание первого шаблона

    По умолчанию Django ищет шаблоны в папке templates внутри каждого приложения. Чтобы все работало корректно, нам нужно создать правильную структуру папок.

    Внутри папки вашего приложения blog создайте директорию templates, а внутри неё — еще одну директорию blog. Да, это выглядит как тавтология (blog/templates/blog/), но это стандарт именования в Django, который позволяет избежать конфликтов имен между разными приложениями.

    Создайте файл blog/templates/blog/post_list.html.

    Использование функции render

    Теперь нам нужно научить наше представление (View) использовать этот файл. Откройте blog/views.py и измените функцию post_list. Вместо HttpResponse мы будем использовать функцию render.

    Обратите внимание на третий аргумент — словарь {'posts': posts}. Ключ этого словаря ('posts') станет именем переменной, доступной внутри шаблона.

    Язык шаблонов Django (DTL)

    Теперь откроем наш пустой файл post_list.html и добавим туда HTML-код с использованием Django Template Language (DTL). DTL — это мощный инструмент, который позволяет внедрять логику прямо в верстку.

    Основные конструкции DTL:

    * {{ variable }}Переменные. Выводят значение переменной на экран. * {% tag %}Теги. Управляют логикой (циклы, условия). * {{ variable|filter }}Фильтры. Изменяют отображение данных.

    Напишем код для нашего списка постов:

    Разбор кода шаблона

  • {% for post in posts %}: Это цикл. Мы перебираем список posts, который передали из views.py. Все, что находится между {% for %} и {% endfor %}, будет повторено для каждого поста.
  • {{ post.title }}: Мы обращаемся к атрибутам объекта модели так же, как в Python — через точку.
  • {{ post.text|linebreaksbr }}: Здесь мы используем фильтр linebreaksbr. Он превращает переносы строк в тексте поста в HTML-теги <br>, чтобы текст не сливался в одну строку.
  • !Визуализация того, как данные из View объединяются с Шаблоном для создания итоговой HTML-страницы.

    Наследование шаблонов: принцип DRY

    Сейчас наш шаблон содержит базовую структуру HTML (<html>, <head>, <body>). Если мы создадим еще одну страницу (например, для просмотра одного поста), нам придется копировать этот код. Если мы захотим добавить меню на все страницы, нам придется править каждый файл. Это нарушает принцип DRY (Don't Repeat Yourself — Не повторяйся).

    Django предлагает элегантное решение — наследование шаблонов.

    Создание базового шаблона

    Создайте файл blog/templates/blog/base.html. В нем мы опишем общий каркас сайта:

    Ключевой момент здесь — тег {% block content %}. Этот тег определяет место, куда дочерние шаблоны будут вставлять свой уникальный контент.

    Использование наследования

    Теперь перепишем blog/templates/blog/post_list.html, чтобы он наследовался от base.html:

    Тег {% extends 'blog/base.html' %} говорит Django: «Возьми за основу base.html и замени в нем блок content на то, что написано ниже».

    Работа со статическими файлами (CSS)

    Наш сайт работает, но выглядит как документ из 90-х. Чтобы добавить дизайн, нам нужны статические файлы (CSS, JavaScript, изображения).

    В Django статика хранится отдельно от шаблонов. Структура папок аналогична шаблонам: blog/static/css/.

  • Создайте папку static внутри папки blog.
  • Внутри static создайте папку css.
  • Создайте файл blog/static/css/blog.css.
  • Напишем немного стилей в blog.css:

    Подключение CSS в шаблоне

    Теперь нужно подключить этот файл в нашем base.html. Для этого нужно сделать две вещи:

  • Загрузить библиотеку статики в начале шаблона: {% load static %}.
  • Использовать тег static для генерации ссылки на файл.
  • Обновим blog/templates/blog/base.html:

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

    Детализация поста и URL-адреса

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

    В post_list.html у нас была пустая ссылка: <a href="">. В Django не принято писать URL вручную (например, /post/1/), так как при изменении маршрутизации все ссылки сломаются. Вместо этого мы используем тег {% url %}.

    Измените ссылку в post_list.html:

    Разберем конструкцию {% url 'post_detail' pk=post.pk %}: * 'post_detail' — это имя маршрута, которое мы задали в urls.py (параметр name='post_detail'). * pk=post.pk — мы передаем первичный ключ (ID) конкретного поста в URL.

    Теперь создадим шаблон blog/templates/blog/post_detail.html:

    Не забудьте обновить post_detail в views.py, чтобы он использовал render:

    Заключение

    Сегодня мы превратили наш набор данных в полноценный веб-сайт. Мы изучили:

  • Шаблоны: Как отделять HTML от Python-кода.
  • DTL: Как использовать переменные, циклы и фильтры.
  • Наследование: Как создавать базовые шаблоны для соблюдения принципа DRY.
  • Статика: Как подключать CSS-файлы для стилизации страниц.
  • URL-теги: Как создавать динамические ссылки между страницами.
  • Теперь ваш блог имеет структуру и стиль. Но пока что добавлять посты можно только через админ-панель. В следующей статье мы научимся работать с Формами (Forms), чтобы пользователи могли создавать и редактировать записи прямо на сайте.

    5. Формы и панель администратора: взаимодействие с пользователем и управление контентом

    Формы и панель администратора: взаимодействие с пользователем и управление контентом

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

    Сегодня мы сделаем наш сайт интерактивным. Мы разберем, как работают Django Forms, научимся получать данные от пользователей, обрабатывать их и сохранять в базу. Кроме того, мы превратим стандартную панель администратора в мощный инструмент управления контентом.

    Django Forms: зачем они нужны?

    В классическом HTML для отправки данных используется тег <form>. Вы могли бы написать его вручную в шаблоне, а затем во views.py вытаскивать данные из объекта request.POST. Но этот путь тернист и опасен:

  • Валидация: Вам придется вручную проверять, заполнил ли пользователь обязательные поля, является ли email валидным адресом, а дата — датой.
  • Безопасность: Ручная обработка данных открывает уязвимости для SQL-инъекций и XSS-атак.
  • Рутина: Вы будете писать один и тот же код проверки снова и снова.
  • Django предлагает элегантное решение — модуль django.forms. Он берет на себя генерацию HTML, валидацию данных и их очистку (cleaning).

    ModelForm: форма на основе модели

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

    Чтобы не дублировать код, Django предоставляет класс ModelForm. Он автоматически создает форму на основе полей вашей модели.

    Давайте создадим файл forms.py внутри папки нашего приложения blog (на одном уровне с models.py и views.py).

    Разберем этот код: * Мы импортируем forms и нашу модель Post. * Класс PostForm наследуется от forms.ModelForm. * Внутри класса Meta мы указываем, какую модель использовать (model = Post) и какие поля должны быть в форме (fields). Обратите внимание, что мы не включили created_date и published_date, так как они должны выставляться автоматически или администратором, а не обычным пользователем.

    Обработка формы во View (Представлении)

    Теперь нам нужно создать View-функцию, которая будет делать две вещи:

  • Показывать пустую форму, когда пользователь впервые заходит на страницу (GET-запрос).
  • Сохранять данные, когда пользователь нажимает кнопку «Отправить» (POST-запрос).
  • Этот паттерн является стандартом в веб-разработке.

    !Логика обработки формы: разделение потоков GET и POST запросов

    Добавим новую функцию в blog/views.py. Не забудьте импортировать PostForm и redirect:

    Важные моменты:

    * request.method: Позволяет определить тип HTTP-запроса. * form.is_valid(): Запускает механизм валидации Django. Если поля заполнены корректно, метод вернет True. * commit=False: Полезный прием. Он позволяет получить объект модели из формы, изменить его (например, автоматически проставить автора) и только потом сохранить в базу.

    Создание шаблона с формой

    Теперь создадим файл blog/templates/blog/post_edit.html:

    Здесь есть два критически важных элемента:

  • {% csrf_token %}: Это защита от Cross-Site Request Forgery (межсайтовой подделки запроса). Django требует наличие этого токена в любой форме, отправляющей данные методом POST. Без него сервер вернет ошибку 403 Forbidden.
  • {{ form.as_p }}: Эта магическая переменная превратит ваш объект формы в набор HTML-тегов <input> и <label>, обернутых в параграфы <p>. Это самый быстрый способ вывести форму.
  • Осталось добавить маршрут в blog/urls.py:

    Теперь, перейдя по адресу /post/new/, вы увидите форму создания поста. После заполнения вы будете перенаправлены на страницу просмотра этой записи.

    Редактирование записей

    Создание — это хорошо, но что если мы допустили опечатку? Нам нужна возможность редактирования. Прелесть ModelForm в том, что мы можем использовать ту же самую форму и тот же самый шаблон.

    Добавим View для редактирования в blog/views.py:

    Главное отличие здесь — аргумент instance=post. Он говорит Django: «Возьми эту форму и заполни её данными из объекта post». При сохранении Django выполнит SQL-запрос UPDATE вместо INSERT.

    Не забудьте добавить URL:

    И кнопку редактирования в шаблон post_detail.html:

    Панель администратора: профессиональная настройка

    Мы уже заходили в админку (/admin/), но она выглядела довольно базово. Список постов отображался как Post object (1), Post object (2) (пока мы не добавили метод __str__), и там не было фильтров.

    Django позволяет тонко настраивать админку через класс ModelAdmin. Откройте файл blog/admin.py.

    Ранее мы писали просто admin.site.register(Post). Давайте расширим это:

    Что мы добавили:

    * list_display: Определяет, какие поля модели будут показаны в списке записей в виде колонок. Теперь вместо одной строки мы увидим таблицу с заголовком, датами и автором. * list_filter: Добавляет боковую панель с фильтрами. Django автоматически определит тип поля (например, дата) и предложит фильтры «Сегодня», «За последние 7 дней» и т.д. * search_fields: Добавляет строку поиска вверху страницы. Поиск будет вестись по заголовку и тексту поста. * date_hierarchy: Добавляет удобную навигацию по датам над списком постов.

    Теперь ваша админ-панель выглядит как профессиональный инструмент контент-менеджера.

    Заключение

    В этой лекции мы преодолели важный рубеж. Наш сайт перестал быть статичным отображением базы данных. Теперь мы можем:

  • Создавать и редактировать контент через удобные формы на сайте.
  • Безопасно обрабатывать пользовательский ввод с помощью ModelForm и CSRF-токенов.
  • Эффективно управлять большим количеством записей через настроенную админ-панель.
  • Теперь у вас есть полноценный, работающий блог. В следующих уроках мы можем углубиться в вопросы аутентификации пользователей или развертывания (деплоя) нашего приложения на реальном сервере в интернете.