使用Form生成html标签的时候,虽然提供了widget的方法可以自定义标签的要是,但是只能给生成的input标签添加样式,对于生成的label标签无法添加样式。
而很多场景下需要为label和input都添加class以实现自定义样式。
测试环境
创建一个Form,通过Form帮我们生成HTML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
# urls.py 文件,对应关系 path( 'email/' , views.email), # forms.py 文件 from django.forms import Form from django.forms import fields from django.forms import widgets class UserEmail(Form): username = fields.CharField() password = fields.CharField( widget = widgets.PasswordInput(attrs = { 'class' : 'c1' }) ) email = fields.EmailField( widget = widgets.EmailInput(attrs = { 'class' : 'c1' }) ) # views.py 文件 def email(request): obj = forms.UserEmail() print (obj[ 'email' ].label_tag(attrs = { 'class' : 'c1' })) # 其实生成标签的方法是提供attrs参数的 return render(request, 'demo/email.html' , { 'obj' : obj}) |
在html中,直接使用Form帮我生成的表单:
1
2
3
4
5
|
<body> {{ obj.as_p }} {{ obj.email.label_tag }} {{ obj.email }} < / body> |
这里可以看到,input标签里都是有class属性的,但是lable标签里没有,并且Form组件里貌似也没有提供为label标签增加自定义属性的方式。
通过模板语言的自定义函数实现
上面的views里的 print(obj['email'].label_tag(attrs={'class': 'c1'})) ,从输出看,django提供的生成label标签的方法是支持attrs参数实现自定义属性的,问题是在前端使用模板语言的时候只能这样 {{ obj.email.label_tag }} 无法传入参数。这里就自定义个模板语言的函数来解决这个问题。
自定义函数
要自定义函数,按照下面的步骤操作:
在APP下,创建templatetags目录,目录名字很重要不能错。
创建任意 .py 文件,这里文件名随意,比如:myfun.py。
文件里创建一个template.Library()对象,名字是register。这里的对象名字必须是register。
然后写自己的函数,但是都用@register.simple_tag这个装饰器装饰好:
自定义的函数如下:
1
2
3
4
5
6
7
|
# app名/templatetags/myfun.py 文件 from django import template register = template.Library() @register . filter (is_safe = True ) def label_with_classes(value, arg): return value.label_tag(attrs = { 'class' : arg}) |
然后在页面中使用自定义的函数:
1
2
3
4
5
6
7
|
<body> {{ obj.as_p }} {{ obj.email.label_tag }} {{ obj.email }} { % load myfun % } {{ obj.email|label_with_classes: 'c1 c2' }} < / body> |
注意,上面的自定义函数引用的时候参数和参数之间一定不能有空格。
这里还有一个好处,把添加前端样式的代码放到了前端的html里实现了。
为input标签也写一个自定义函数
django默认的方法是在Form里,通过widgets小部件添加attrs参数来实现标签的自定义样式。这是在放在后端实现的。上面已经实现了前端的自定义样式,这里找了到生成input标签的方法,就是as_widget()。
照着样子再写一个子定义函数:
1
2
3
4
5
6
7
8
9
10
11
|
# app名/templatetags/myfun.py 文件 from django import template register = template.Library() @register . filter () def label_with_classes(value, arg): return value.label_tag(attrs = { 'class' : arg}) @register . filter () def widget_with_classes(value, arg): return value.as_widget(attrs = { 'class' : arg}) |
最后,上面搞得难么麻烦,主要是为了可以前端一个for循环,就能把表单按自定义的样式显示出来:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
<body> <link rel = "stylesheet" href = "https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel = "external nofollow" integrity = "sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin = "anonymous" > { % load myfun % } <form class = "form-horizontal" > { % for item in obj % } <div class = "form-group" > {{ item|label_with_classes: 'col-sm-2 control-label' }} <div class = "col-sm-10" > {{ item|widget_with_classes: 'form-control' }} < / div> < / div> { % endfor % } < / form> < / body> |
补充知识:Django Forms组件 的参数配置案例 input样式, 渲染的标签加class 错误信息提示
Forms渲染出标签类型
密码型、文本型、邮箱型框
1
2
3
4
5
6
7
8
9
|
from django.forms import widgets # 自定义格式方法 class UserForm(forms.Form): '''最小4位 且 模式:普通文本''' name = forms.CharField(min_length = 4 , label = '姓名:' ,widget = widgets.TextInput()) '''最小4位 且 模式:密码模式''' pwd = forms.CharField(min_length = 4 , label = '密码:' , widget = widgets.PasswordInput()) |
渲染时添加属性 class=''(便于bootstrap)
1
2
3
4
5
6
7
8
9
10
11
12
|
from django.forms import widgets '''在widgets.类型(加入字典形式的标签信息)''' class UserForm(forms.Form): # 模式:普通文本 标签加上:class="form-control" name = forms.CharField(widget = widgets.TextInput(attrs = { 'class' : 'form-control' })) # 模式:密码模式 标签加上:class="form-control" pwd = forms.CharField(widget = widgets.PasswordInput( attrs = { 'class' : 'form-control' } )) |
渲染自定义错误提示
视图
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
from django.forms import widgets '''追加error_messages参数 dict型式''' class UserForm(forms.Form): # 模式:required=不能为空的提示 name = forms.CharField(min_length = 4 , label = '姓名:' , error_messages = { 'title' : { 'required' : '不能为空哦亲亲' }, 'price' : { 'invalid' : '格式错误(提示方法)' }, # '字段': {'错误类型': '提示信息'} }) # 模式:invalid=格式错误 pwd = forms.CharField(min_length = 4 , label = '密码:' , error_messages = { 'title' : { 'required' : '不能为空哦亲亲' }, 'price' : { 'invalid' : '格式错误(提示方法)' }, # '字段': {'错误类型': '提示信息'} }) |
HTML展示错误信息
1
2
3
4
5
6
7
8
9
10
11
12
|
< form action = "" method = "post" novalidate = "novalidate" > <!--要自定义提示必须 novalidate="novalidate"--> {% csrf_token %} {% for field in form %} < p > {{ field.label }}{{ field }} < span >{{ field.errors.0 }}</ span > <!--错误信息固定:field.errors.0 --> </ p > {% endfor %} < p >< input type = "submit" value = "提交" ></ p > </ form > |