django为Form生成的label标签添加class方式
作者:骑士救兵 时间:2022-08-13 12:01:44
使用Form生成html标签的时候,虽然提供了widget的方法可以自定义标签的要是,但是只能给生成的input标签添加样式,对于生成的label标签无法添加样式。
而很多场景下需要为label和input都添加class以实现自定义样式。
测试环境
创建一个Form,通过Form帮我们生成HTML:
# 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帮我生成的表单:
<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这个装饰器装饰好:
自定义的函数如下:
# 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})
然后在页面中使用自定义的函数:
<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()。
照着样子再写一个子定义函数:
# 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循环,就能把表单按自定义的样式显示出来:
<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渲染出标签类型
密码型、文本型、邮箱型框
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)
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'}
))
渲染自定义错误提示
视图
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展示错误信息
<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>
来源:https://blog.51cto.com/steed/2120211