如何使用 Django 1.11 基于模板的表单渲染将 CSS class 添加到 widget/field

How to add CSS class to widget/field with Django 1.11 template-based form rendering

注意:这个问题不应该与过去类似但在 Django 1.11 之前的问题混淆,当时他们发布了基于模板的表单渲染。

我知道 Django 现在有基于模板的表单呈现。据我了解,这应该可以解决必须从视图或表单中注入 CSS class 的问题,而不是将所有 HTML/CSS 保留在模板中。

这是我的目标:让我的表单和视图专注于 显示什么,我的模板专注于 如何显示。所以我想在我的模板中保留所有 HTML/CSS。

所以,我的问题是:

我可能对这项新功能有一些误解,所以如果我误解了,请随时告诉我这是否不是它的工作原理或者我问的是不可能的事情。理想情况下,我想对主模板实施这些表单呈现更改。

示例问题

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 小部件获得 class):

<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 %}

据我从 release notes of Django 1.11 和我自己的测试中了解到,新功能 允许我们轻松自定义小部件的呈现方式只需为每种小部件类型提供 HTML 文件。在以前的 Django 版本中,您必须提供 forms.widget.Widget 的子 class 并将该小部件一一分配给您的 model/form 字段 (IIRC)。

如果你想让所有 TextInput 小部件都有一个特定的 class,你将不得不添加你的自定义 text.html(可能还有你自己的 attrs.html 作为出色地)。

例如,假设我有一个带有 main 应用程序的 myforms 项目。根据文档:

If you use the TemplatesSetting renderer, overriding widget templates works the same as overriding any other template in your project. You can’t override built-in widget templates using the other built-in renderers.

所以我们需要在 settings.py 文件中设置渲染器:

FORM_RENDERER = 'django.forms.renderers.TemplatesSetting'

但如果我们只这样做,我们需要为所有 个输入元素提供模板。根据文档:

Using this renderer along with the built-in widget templates requires [...] [adding] 'django.forms' in INSTALLED_APPS and at least one engine with APP_DIRS=True.

因此我们将 django.forms 添加到 INSTALLED_APPS。现在,为了添加我们对 文本输入元素 的自定义,我们需要创建文件 main/templates/django/forms/widgets/text.html 并在其中添加我们的自定义 HTML 代码,例如:

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

因此,如果我们在模板中显示一个表单,那么每当 CharField 需要呈现时,该代码就会出现,例如。

但是 如果您需要每个字段级别的控制,则所有这些都无关紧要,例如,如果每个字段需要不同的 class。那样的话,你应该把我写的和django-widget-tweaks结合起来,这样你就可以有更灵活的widget定制。

继续上面 José Tomás Tocino 的回答,在 Django 1.11 中,我发现我的目录结构需要是:

main/templates/django/forms/widgets/text.html