Как добавить класс CSS в виджет / поле с помощью рендеринга формы на основе шаблона Django 1.11

Примечание. Этот вопрос не следует смешивать с аналогичными вопросами прошлого, но до Django 1.11, когда они выпустили рендеринг форм на основе шаблонов.

Я понимаю, что в Django теперь есть рендеринг форм на основе шаблонов. Насколько я понимаю, это должно решить проблему внедрения классов CSS из представления или формы, а не сохранения всего HTML / CSS в шаблонах.

Это моя цель: чтобы мои формы и представления были сосредоточены на том, что отображается, а в моих шаблонах - на том, как это отображается. Поэтому я хочу сохранить в своих шаблонах весь HTML / CSS.

Итак, мои вопросы:

  • Как мне добавить класс (например, form-text) ко всем TextInput виджетам из системы шаблонов?
  • Как мне добавить класс (например, alert-warning) ко всем сообщениям об ошибках (сбоям проверки) из системы шаблонов?

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

Пример проблемы

views.py:

class SignUp(generic.edit.CreateView):

    model = models.User
    template_name = 'usermgmt/sign_up.html'
    form_class = forms.UserCreateForm
    success_url = '/sign_up_done/'

templates/master.html (я хочу добавить сюда кое-что, что заставит все TextInput виджеты получить класс):

<html>
<head>
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">
<title>{% block title %}{% endblock %} | Website</title>
</head>
<body>
  <div class="content-wrapper clearfix">
    {% block main %}{% endblock %}
  </div>
</body>
</html>

templates/usermgmt/sign_up.html:

{% extends 'master.html' %}

{% block title %}Sign Up{% endblock %}

{% block main %}
<h1>Sign Up</h1>
<p>Enter your email to sign up!</p>
<form class="form-group" method="post">
  {% csrf_token %}
  <input type="hidden" name="next" value="{{ next }}">
  {{ form.as_p }}
  <button class="btn btn-primary" type="submit">Sign Up</button>
</form>
{% endblock %}

person Greg Schmit    schedule 05.02.2017    source источник


Ответы (2)


Насколько я понял из примечаний к выпуску Django 1.11 и результаты моего собственного тестирования, новые функции только позволяют нам легко настраивать способ отображения виджетов, просто предоставляя файлы HTML для каждого типа виджета. В предыдущих версиях Django вам приходилось предоставлять подкласс forms.widget.Widget и одно за другим назначать этот виджет полям вашей модели / формы (IIRC).

Если вы хотите, чтобы все TextInput виджеты имели определенный класс, вам нужно будет добавить свой собственный text.html (и, возможно, свой собственный attrs.html).

Например, допустим, у меня есть myforms проект с main приложением. Согласно документам:

Если вы используете средство визуализации TemplatesSetting, переопределение шаблонов виджетов работает так же, как переопределение любого другого шаблона в вашем проекте. Вы не можете переопределить встроенные шаблоны виджетов с помощью других встроенных средств визуализации.

Итак, нам нужно установить наш рендерер в файле settings.py:

FORM_RENDERER = 'django.forms.renderers.TemplatesSetting'

Но если мы сделаем только это, нам понадобятся шаблоны для всех элементов ввода. Согласно документам:

Использование этого средства визуализации вместе со встроенными шаблонами виджетов требует [...] [добавления] 'django.forms' в INSTALLED_APPS и хотя бы одного движка с APP_DIRS = True.

Итак, мы добавляем django.forms к INSTALLED_APPS. Теперь, чтобы добавить наши настройки, скажем, для элементов ввода текста, нам нужно создать файл main/templates/django/forms/widgets/text.html и добавить туда наш собственный HTML-код, например:

<input type="text" class="myclass" value="{{widget.value}}">

Итак, если мы показываем форму в шаблоне, этот код будет появляться всякий раз, когда нужно отобразить CharField, например.

Но все это не имеет значения, если вам нужен уровень управления для каждого поля, например, если для каждого поля нужен другой класс. В этом случае вам следует объединить то, что я написал, с django-widget-tweaks, чтобы может иметь более гибкую настройку виджета.

person José Tomás Tocino    schedule 06.03.2017
comment
Отличный ответ; как мне оформить все сообщения об ошибках с классом custom-error? Сообщения об ошибках - это виджет? На самом деле мне это не нужно, так как я могу стилизовать ошибку, вручную вводя field.errors, но мне любопытно, возможно ли это простым способом, создав шаблон. - person Greg Schmit; 07.03.2017
comment
расположение шаблона выше обновлено в соответствии с ответом Анны Томас - person Yunti; 22.11.2017

Продолжая ответ Хосе Томаса Точино выше, в Django 1.11 я обнаружил, что моя структура каталогов должна быть:

основной / шаблоны / django / формы / виджеты / текст.html

person Anna Howell    schedule 21.05.2017
comment
Я ценю усилия, но, вероятно, это должен быть комментарий или правка. Я понимаю, что вы новый пользователь. - person Greg Schmit; 22.05.2017
comment
@GregSchmit Вы правы, я пытался прокомментировать, но не получил репутации. Я решил, что какой-то комментарий (надеюсь, поможет следующему человеку) лучше, чем ничего вообще. Спасибо, что не проголосовали против меня. - person Anna Howell; 23.05.2017