Для ввода различных данных в Django используются формы – специальный инструмент, обеспечивающий вывод полноценной веб-формы, а также обеспечивающий проверку внесенной информации на корректность. Если форма связана с моделью, она может самостоятельно сохранить информацию в базе данных.
В качестве примера создадим форму, предназначенную для ввода объявлений и связанную с созданной ранее моделью Bb. Назовем новый класс BbForm.
Если запущен отладочный веб-сервер, его необходимо остановить. Далее в приложении bboard создадим модуль forms.py со следующим кодом:
from .models import Bb class BbForm(modelForm): class Meta: model = Bb fields = ('title', 'content', 'price', 'rubric')
Класс формы, связанной с моделью, является производным от ModelForm (модуль django.forms). Для настроек параметров формы используется вложенный класс Meta: связанная модель (атрибут model) и набор полей, которые будут отображаться в форме (атрибут fields).
Контроллеры-классы
Для обработки форм, связанных с моделью, можно использовать контроллеры-функции. Однако лучше для этих целей задействовать высокоуровневый контроллер-класс, который возьмет на себя часть функций по обработке данных и выводу форму.
В качестве примера создадим новый контроллер класс BbCreateView (объявим в модуле views.py). Добавим в файл следующий код:
from django.views.generic.edit import CreateView from .forms import BbForm class BbCreateView(CreateView): template_name = 'bboard/create.html' form_class = BbForm success_url = ' /bboard/' def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context[' rubrics'] = Rubric.objects.all() return context
Новый контроллер класс является производным от класса CreateView (модуль django.views.generic.edit). Базовый класс способен выполнять основные операции – создание формы, вывод указанного шаблона, перенаправление пользователя после завершения операции, а также получение, проверку и корректное сохранение введенных данных.
Атрибуты объявленного класса содержат:
— form_class – содержит ссылку на класс формы, который связан с моделью;
— template_name – информация о пути к файлу шаблона для создания страницы с формой;
— success_url – позволяет указать страницу для автоматического перенаправления пользователя после успешного сохранения данных.
Поскольку в нашем проекте на всех страница сайта должен выводиться список рубрик, переопределим метод get_context_data(), который формирует контекст шаблона. Это позволяет добавить в возвращаемый результат список рубрик.
Код шаблона bboard\create.html:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Добавление объявления | Доска объявлений</title> </head> <body <h1>Добавления объявления</h1> <div> <a href="{% url 'index' %}">Главная</a> {% for rubric in rubrics %} <a href="{% url 'by_rubric' rubric.pk %}"> {{ rubric.name }}</a> {% endfor %} </div> <form method=''post> {% csrf_token %} {{ form.as_p }} <input type="submit" value="Добавить"> </form> </body> </html>
Стоит отметить следующее:
— для хранения формы в контексте шаблона используется переменная form, за создание которой отвечает контроллер-класс;
— элементы формы, расположенные на отдельных абзацах, выводятся при помощи метода as_p() класса формы;
— используемый метод as_p() генерирует только код, отвечающий за формирование элементов управления. Теги <input> и <form> пользователь создает самостоятельно.
Если не указывать интернет-адрес, по которому необходимо отправить данные из формы, они будут отправлены на адрес, с которого загружена текущая страница. В нашем случае это контроллер-класс BbCreateView, который и обеспечит их обработку и сохранение.
— в теге <form> также присутствует тег шаблонизатора csrf_token. Данный тег создает в форме специальное скрытое поле, в котором хранится цифровой жетон. Его наличие позволяет контроллеру проверить, что данные полученные с текущего сайта. Данный инструмент является частью подсистемы безопасности Django.
Далее необходимо добавить в urls.py пакета приложения маршрут, который свяжет адрес с контроллером CreateView:
. . . from .views import index, by_rubric, BbCreateView urlpatterns = [ path('add/', BbCreateView.as_view(), name='add'), . . . ]
Теперь в вызов функции path() автоматически подставляются данные, полученные от метода as_view() контроллера-класса.
Для удобства также добавим в панель навигации, которая отображается на всех страницах, ссылку на страницу добавления нового объявления:
<a href="{% url 'add' %}">Добавить</a>
Теперь можно запустить отладочный сервер и проверить работу новой формы. После заполнения полей и нажатия кнопки Добавить новое объявление будет сохранено и отобразится на главной странице.
При объявлении класса BbCreateView ранее мы явно указали адрес перенаправления (через атрибут success_url). Предпочтительнее использовать обратное разрешение. Изменим код класса BbCreateView в views.py:
from django.urls import reverse_lazy class BbCreateView(CreateView): . . . success_url = reverse_lazy('index') . . .
Функция reverse_lazy (модуль django.url) получает имя маршрута и URL-параметры, если они используются. В качестве результата возвращается готовый интернет-адрес.