Создание фильтра. Приложение core

Форма регистрации готова — но только с точки зрения бэкендера. А ведь в мире есть фронтендеры, и им нужно, чтобы в тегах 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 для старта.

Откройте или обновите страницу регистрации. Форма выглядит чисто, красиво и профессионально:





Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: