Форма регистрации готова — но только с точки зрения бэкендера. А ведь в мире есть фронтендеры, и им нужно, чтобы в тегах input
выводился HTML-атрибут class
: без него они не смогут правильно сверстать страницу.Сейчас код формы такой:
<label for="id_username">
Имя пользователя
<span class="required text-danger">*</span>
</label>
<div>
<input
type="text"
name="username"
maxlength="150"
autofocus
required id="id_username"
>
<small id="id_username-help" class="form-text text-muted">
Обязательное поле. Не более 150 символов.
Только буквы, цифры и символы @/./+/-/_.
</small>
</div>
А вот код, который должен быть:
<label for="id_username">
Имя пользователя
<span class="required text-danger">*</span>
</label>
<input
type="text"
name="username"
maxlength="150"
autofocus
class="form-control"
required id="id_username"
>
<small id="id_username-help" class="form-text text-muted">
Обязательное поле. Не более 150 символов.
Только буквы, цифры и символы @/./+/-/_.
</small>
Полям input
не хватает атрибута class="form-control"
. Без него фронтендеры тоскуют. Надо им помочь.
Приложение core
С фильтрами шаблонов вы уже имели дело: {{ var|linebreaksbr }}
, {{ var|safe }}
, {{ var|date }}
; фильтры — полезный инструмент, обрабатывающий переменные прямо в шаблоне. С помощью фильтров можно добавить CSS-классы в нужные теги. Но для этого надо написать собственный фильтр.
Фильтры — универсальный инструмент, который может пригодиться в любом приложении проекта; хорошим тоном будет создать и зарегистрировать служебное приложение core
, и все сущности, касающиеся всего проекта в целом, хранить в нём.Через консоль создайте приложение core, зарегистрируйте его в settings.py. В директории /core создайте папку /templatetags, а в ней — два пустых файла: __init__.py
и user_filters.py. А другие файлы можно удалить.У вас должна получится такая структура:
└── yatube
├── posts
├── core # Приложение для хранения всякого
│ ├── templatetags
│ │ ├── __init__.py
│ │ └── user_filters.py
│ ├── __init__.py
│ └── apps.py
├── templates
├── users
└── manage.py
Файл __init__.py
сообщает системе, что директория /templatetags — это пакет, который можно импортировать в код. А в файле user_filters.py будет код фильтра, который даст возможность указывать CSS-класс в HTML-коде любого поля формы.
Создание собственного фильтра в шаблонах
У объекта field есть метод as_widget()
. Ему можно передать параметр с перечнем HTML-атрибутов, которые мы хотим изменить.
Финальный код фильтра будет выглядеть так:
from django import template
# В template.Library зарегистрированы все встроенные теги и фильтры шаблонов;
# добавляем к ним и наш фильтр.
register = template.Library()
@register.filter
def addclass(field, css):
return field.as_widget(attrs={'class': css})
# синтаксис @register... , под который описана функция addclass() -
# это применение "декораторов", функций, меняющих поведение функций
# Не бойтесь соб@к
Теперь в коде шаблона можно указать фильтр addclass с параметром form-control: {{ field|addclass:'form-control' }}
.Чтобы фильтр был доступен в шаблоне — предварительно загрузите его в шаблон тегом {% load user_filters %}
.Финальный код шаблона формы регистрации будет выглядеть так:
{% extends "base.html" %}
{% block title %}Зарегистрироваться{% endblock %}
{% block content %}
<div class="row justify-content-center">
<div class="col-md-8 p-5">
<div class="card">
<div class="card-header">Зарегистрироваться</div>
<div class="card-body">
{% load user_filters %} {# Загружаем фильтры #}
{% if form.errors %}
{% for field in form %}
{% for error in field.errors %}
<div class="alert alert-danger">
{{ error|escape }}
</div>
{% endfor %}
{% endfor %}
{% for error in form.non_field_errors %}
<div class="alert alert-danger">
{{ error|escape }}
</div>
{% endfor %}
{% endif %}
<form method="post" action="{% url 'users:signup' %}">
{% csrf_token %}
{# Выводим поля в цикле, по отдельности #}
{% for field in form %}
<div class="form-group row my-3">
<label for="{{ field.id_for_label }}">
{{ field.label }}
{% if field.field.required %}
<span class="required text-danger">*</span>
{% endif %}
</label>
{# К полю ввода добавляем атрибут class #}
{{ field|addclass:'form-control' }}
{% if field.help_text %}
<small
id="{{ field.id_for_label }}-help"
class="form-text text-muted"
>
{{ field.help_text|safe }}
</small>
{% endif %}
</div>
{% endfor %}
<div class="col-md-6 offset-md-4">
<button type="submit" class="btn btn-primary">
Зарегистрироваться
</button>
</div>
</form>
</div> <!-- card body -->
</div> <!-- card -->
</div> <!-- col -->
</div> <!-- row -->
{% endblock %}
Внимание: если сервер разработчика запущен, а вы изменили файлы проекта — Django, как правило, видит это и перезапускает сервер. Но иногда Django может не заметить изменений; в такой ситуации перезапустите dev-сервер вручную: в окне терминала нажмите Ctrl+C для остановки сервера и выполните команду $ python manage.py runserver
для старта.
Откройте или обновите страницу регистрации. Форма выглядит чисто, красиво и профессионально: