如何使用 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。
所以,我的问题是:
- 如何向模板系统中的所有
TextInput
小部件添加 class(例如,form-text
)?
- 如何向模板系统的所有错误消息(验证失败)添加 class(例如,
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
小部件获得 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
注意:这个问题不应该与过去类似但在 Django 1.11 之前的问题混淆,当时他们发布了基于模板的表单渲染。
我知道 Django 现在有基于模板的表单呈现。据我了解,这应该可以解决必须从视图或表单中注入 CSS class 的问题,而不是将所有 HTML/CSS 保留在模板中。
这是我的目标:让我的表单和视图专注于 显示什么,我的模板专注于 如何显示。所以我想在我的模板中保留所有 HTML/CSS。
所以,我的问题是:
- 如何向模板系统中的所有
TextInput
小部件添加 class(例如,form-text
)? - 如何向模板系统的所有错误消息(验证失败)添加 class(例如,
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
小部件获得 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