Курс по Django: https://stepik.org/a/183363
Архив проекта: 43_sitewomen.zip
На данный момент
мы с вами, в целом, познакомились с механизмом маршрутизации, построения
моделей, ORM Django, работы с
шаблонами и использованием админ-панели. Конечно, это далеко не полный
функционал фреймворка Django и мы еще будем возвращаться к
этим темам, но на этом занятии мы коснемся новой темы – работы с формами.
Те из вас, кто
уже создавал свои сайты, знают, что формы – это один из важнейших элементов
большинства сайтов. Например, когда мы выполняем авторизацию или регистрацию,
то появляется страница с полями ввода, чекбоксами, кнопками, списками и другими
элементами интерфейса:
Это и есть
формы. В HTML они задаются
тегом <form> и служат
для передачи на сервер пользовательской информации, например, логина и пароля
для входа на сайт. На этом занятии мы увидим, как реализуются формы во
фреймворке Django. Подробную
документацию об этом вы можете почитать в разделе «Формы» на странице сайта:
https://docs.djangoproject.com/en/4.2/#forms
Первое, что
нужно знать, это то, что формы в Django можно создавать либо
в связке с моделью какой-либо таблицы БД. Тогда получаем формы, связанные с
моделью. Например, когда мы выполняем авторизацию или регистрацию на сайте, то
этот процесс, очевидно, связан с данными таблиц. Соответственно, используются
формы, связанные с моделями. Либо можно создавать независимые формы, не
привязанные к моделям. Например, когда создается простой поиск или идет
отправка письма на электронную почту. Если при этом обращение к БД не
требуется, то и форма создается как независимая, самостоятельная.
Сначала мы
рассмотрим форму, не связанную с моделью, хотя и сделаем это на примере
добавления статей в БД. Но, затем, модифицируем ее и превратим в форму,
связанной с моделью.
Начнем с того,
что в главном меню у нас уже есть пункт для добавления статей и функция
представления addpage (в файле women/views.py). Немного
изменим эту функцию так, чтобы она отображала шаблон addpage.html:
def addpage(request):
return render(request, 'women/addpage.html', {'menu': menu, 'title': 'Добавление статьи'})
А сам шаблон addpage.html определим так:
{% extends 'base.html' %}
{% block content %}
<h1>{{title}}</h1>
Содержимое страницы
{% endblock %}
Теперь, при
обновлении увидим полноценную страницу для добавления нового поста.
Давайте вначале
сформируем форму вручную. Запишем в PyCharm вместо тега <p> и строки
слово form. Нажмем Tab и сразу
появится тег form в виде:
Внутри этого
тега для примера запишем следующий тег input:
<form action="">
<input type="text">
</form>
Обновим страницу
и увидим в окне браузера на странице поле ввода. Как вы догадались, оно
текстовое, так как имеет атрибут type="text".
Давайте добавим
еще несколько полей, например:
<form action="">
<input type="text">
<input type="checkbox">
<input type="number">
<input type="password">
</form>
В
действительности, типов этих полей огромное количество. Все их можно посмотреть
в справочнике или на специализированных сайтах. Довольно неплохой ресурс можно
найти по этой ссылке:
https://www.w3schools.com/html/html_forms.asp
Чтобы добавить
пояснения к этим полям, обычно, используют тег label следующим
образом:
<form action="">
<label for="id_1">Текст: </label><input type="text" id="id_1">
<label for="id_2">Отметка: </label><input type="checkbox" id="id_2">
<label for="id_3">Число: </label><input type="number" id="id_3">
<label for="id_4">Пароль: </label><input type="password" id="id_4">
</form>
И, давайте,
расположим их в столбик, каждый на своей строке. Я сделаю это с помощью тега
абзаца p:
<form action="">
<label for="id_1">Текст: </label><input type="text" id="id_1"></p>
<label for="id_2">Отметка: </label><input type="checkbox" id="id_2"></p>
<label for="id_3">Число: </label><input type="number" id="id_3"></p>
<label for="id_4">Пароль: </label><input type="password" id="id_4"></p>
</form>
У нас с вами
получилось уже нечто вразумительное. Но форма пока не функциональна. Чтобы она
отправляла данные на сервер, необходимо добавить кнопку специального типа submit:
<form action="">
...
<button type="submit">Отправить</button></p>
</form>
(Параметр type со значением submit внутри формы у
кнопки можно и не прописывать, но так понятнее ее назначение.)
Перейдем в
форму, нажмем на эту кнопку и наша страница обновилась. Кроме того, в URL адресе появился
знак вопроса. Он символизирует начало строки с данными GET-запроса. Но
почему сейчас никаких данных нет? Дело в том, что у каждого поля дополнительно
нужно прописать специальный атрибут name с именем
параметра поля. Сделаем это:
name="field_text"
name="field_check"
name="field_num"
name="field_psw"
Теперь, при
отправке формы GET-запрос стал принимать вид:
http://127.0.0.1:8000/addpage/?field_text=&field_num=&field_psw=
То есть, здесь
после знака вопроса через амперсанд идут данные в формате ключ=значение. Так
как значений нет, то просто перечисляются поля.
Давайте введем
какие-либо данные в форму и снова отправим их. Получим следующий вид GET-запроса:
http://127.0.0.1:8000/addpage/?field_text=aaa&field_check=on&field_num=123&field_psw=asd
Эти данные
сервер передает во фреймворк Django, он их упаковывает в словарь request.GET и там мы
получаем к ним доступ. Давайте для примера я поставлю точку останова в функции
обработчике addpage() данной страницы и, смотрите, в словаре request.GET, как
раз находится вся переданная информация из формы. Причем, данные отправляются в
функцию addpage() по той причине, что мы в атрибуте action тега form ничего не
указали. Если, например, мы там укажем слеш:
<form action="/">
...
</form>
то обработчиком
формы будет считаться главная страница. Но, нам это не нужно и я оставлю пустые
кавычки.
У тега form есть еще один
важный атрибут method, который определяет тип запроса для
отправки данных формы. По умолчанию используется метод GET, то есть, GET-запрос, что мы
только что и видели. Но этот запрос плох тем, что все данные пользователи видят
в строке браузера. Например, так отправлять логины, пароли и другую служебную
информацию не стоит. Вместо этого лучше воспользоваться другим типом запроса,
который называется POST:
<form action="" method="post">
...
</form>
Но, если мы
сейчас попробуем отправить данные, то возникнет ошибка из-за отсутствия
специального поля CSRF. В двух словах, он нужен от защиты межсайтовых атак
и фреймворк Django в целях безопасности
его требует при POST-запросах. Добавить его очень просто. Для этого
вначале формы следует прописать специальный шаблонный тег:
Теперь отправка
данных работает без проблем и в словаре request.POST мы можем все их
видеть.
В рамках данного
курса я не буду углубляться в построение форм на уровне HTML-документа.
Введение в эту тему уже есть в курсе по HTML и CSS. И я полагаю,
что вы уже владеете этим материалом. Если нет, то посмотрите. Он небольшой и
несложный:
https://www.youtube.com/playlist?list=PLA0M1Bcd0w8wRiyGX_9y-fUiBPi1vqaTb
На следующем
занятии мы продолжим эту тему и посмотрим, как можно автоматизировать
формирование HTML-форм с помощью
классов форм фреймворка Django.
Курс по Django: https://stepik.org/a/183363