一、forms组件使用
form django import forms
1 自定义一个类,类需要继承forms.Form
自定义类的字段 映射 模板(html)中的form表单中的各种标签
2. 模板利用 RegForm类的实例对象 form_obj进行渲染:
自定义类RegForm的属性 CharField字段 映射 form表单的input标签
1. form_obj.as_p --> 简单演示
2. form_obj.username --> input标签
form_obj.username.label --> label名称(即label标签)
form_obj.username.id_for_label --> label标签for属性使用的id
form_obj.errors --> 用ul标签把所有的错误展示出来
form_obj.username.errors.0 --> 取具体某个input标签(即RegForm属性字段)的第一个错误提示信息
3. 视图views.py:
1. 实例化
form_obj = RegForm(request.POST)
2. 数据有效性校验
form_obj.is_valid()
- true 表示数据没有问题
- form_obj.cleaned_data --> 保存经过校验的数据的大字典
类示例:
from django import forms
from django.core.validators import RegexValidator
from formapp import models
class RegForm(forms.Form):
username = forms.CharField(
min_length=2, max_length=8, label='用户名',
error_messages={'min_length': '用户名不得少于2位', 'max_length': '用户名不得超过8位',
'required': '用户名不能为空'},
widget=forms.widgets.TextInput(
attrs={'class': 'form-control', 'placeholder': '请输入用户名'}
)
)
password = forms.CharField(
label='密码', error_messages={'required': '密码不能为空'},
widget=forms.widgets.PasswordInput(
attrs={'class': 'form-control', 'placeholder': '请输入密码'},
render_value=True
)
)
re_pwd = forms.CharField(
label='确认密码', error_messages={'required': '确认密码不能为空'},
widget=forms.widgets.PasswordInput(
attrs={'class': 'form-control', 'placeholder': '请重复密码'},
render_value=True
)
)
phone = forms.CharField(
label='手机号', error_messages={'required': '手机号不能为空'},
validators=[RegexValidator(r'1[3-9]\d{9}$'), ],
widget=forms.widgets.TextInput(
attrs={'class': 'form-control', 'placeholder': '请输入手机号'},
)
)
gender = forms.ChoiceField(
label='性别',
choices=((1, '男'), (2, '女'), (3, '保密')),
initial=3,
widget=forms.widgets.RadioSelect(
attrs={'class': 'list-inline'}
)
)
hobby = forms.MultipleChoiceField(
label='爱好',
widget=forms.widgets.CheckboxSelectMultiple(
attrs={'class': 'list-inline'}
)
)
"""
forms组件ChoiceField字段的choices若写成动态的从数据库中取数据,由于是静态字段,那么forms会为了
保证页面的加载速度,会把第一次取来的数据放进缓存里边,所以若此时数据库数据有改动,页面并不会随
着动态的改动。我们可以有两种方式解决这个问题。
"""
# 总结:静态字段,获取的值无法实时更新
# 重写父类__init__()
def __init__(self, *args, **kwargs):
super(RegForm, self).__init__(*args, **kwargs)
self.fields['hobby'].choices = models.Hobby.objects.all().values_list('id', 'name')
# 把forms字段跟models绑定
# from django.forms import models as form_model
#
# hobby = form_model.ModelMultipleChoiceField(
# queryset=models.Hobby.objects.all().values_list(),
# label='爱好',
# widget=forms.widgets.CheckboxSelectMultiple(
# attrs={'class': 'list-inline'}
# )
# )
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <title>注册</title>
6 <link rel="stylesheet" href="/static/css/bootstrap/bootstrap3.3.7-min.css">
7 </head>
8 <body>
9 <div class="container col-md-4 col-md-push-3" style="margin-top: 80px">
10
11 <form class="form-horizontal" action="{% url 'reg' %}" novalidate method="post">
12 {% csrf_token %}
13 <div class="form-group">
14 <label class="col-sm-3 control-label"
15 for="{{ form_obj.username.id_for_label }}">{{ form_obj.username.label }}</label>
16 <div class="col-sm-9">
17 {{ form_obj.username }}
18 {{ form_obj.username.errors.0 }}
19 </div>
20 </div>
21 <div class="form-group">
22 <label class="col-sm-3 control-label"
23 for="{{ form_obj.password.id_for_label }}">{{ form_obj.password.label }}</label>
24 <div class="col-sm-9">
25 {{ form_obj.password }}
26 {{ form_obj.password.errors.0 }}
27 </div>
28 </div>
29 <div class="form-group">
30 <label class="col-sm-3 control-label"
31 for="{{ form_obj.re_pwd.id_for_label }}">{{ form_obj.re_pwd.label }}</label>
32 <div class="col-sm-9">
33 {{ form_obj.re_pwd }}
34 {{ form_obj.re_pwd.errors.0 }}
35 </div>
36 </div>
37 <div class="form-group">
38 <label class="col-sm-3 control-label"
39 for="{{ form_obj.phone.id_for_label }}">{{ form_obj.phone.label }}</label>
40 <div class="col-sm-9">
41 {{ form_obj.phone }}
42 {{ form_obj.phone.errors.0 }}
43 </div>
44 </div>
45 <div class="form-group">
46 <label class="col-sm-3 control-label">{{ form_obj.gender.label }}</label>
47 <div class="col-sm-9" style="margin-top: 5px">
48 {{ form_obj.gender }}
49 </div>
50 </div>
51 <div class="form-group">
52 <label class="col-sm-3 control-label">{{ form_obj.hobby.label }}</label>
53 <div class="col-sm-9" style="margin-top: 6px">
54 {{ form_obj.hobby }}
55 </div>
56 </div>
57 <div class="form-group">
58 <div class="col-sm-push-4 col-sm-7">
59 <button type="submit" class="btn btn-block btn-lg btn-success">注册</button>
60 </div>
61 </div>
62 </form>
63
64 </div>
65 </body>
66 </html>
1 from django.shortcuts import render, HttpResponse
2 from formapp.forms import RegForm
3 # Create your views here.
4
5
6 def reg(request):
7 form_obj = RegForm()
8 if request.method == 'POST':
9 form_obj = RegForm(request.POST)
10 if form_obj.is_valid():
11 return HttpResponse('注册成功')
12 return render(request, 'reg.html', {'form_obj': form_obj})
forms组件ChoiceField字段的choices若写成动态的从数据库中取数据,那么forms会为了保证页面的加载速度,
会把第一次取来的数据放进缓存里边,所以若此时数据库数据有改动,页面并不会随着动态的改动。我们可以
有两种方式解决这个问题。
参考:https://www.cnblogs.com/liwenzhou/p/9030211.html
方式一: 重写父类__init__()
def __init__(self, *args, **kwargs):
super(RegForm, self).__init__(*args, **kwargs)
self.fields['hobby'].choices = models.Hobby.objects.all().values_list('id', 'name')
方式二:绑定models
# 把forms字段跟models绑定
from django.forms import models as form_model
hobby = form_model.ModelMultipleChoiceField(
queryset=models.Hobby.objects.all().values_list(),
label='爱好',
widget=forms.widgets.CheckboxSelectMultiple(
attrs={'class': 'list-inline'}
)
)
二、forms 的各种校验方法
一、校验器
1.django内置正则校验
from django.core.validators import RegexValidator
validators=[RegexValidator(r'1[3-9]\d{9}$'), ],
2.自定义方法
def name_check(value):
if '哒哒哒' in value:
raise ValidationError("不符合社会主义核心价值观!")
else:
return value
使用:
validators=[ name_check,]
二、局部钩子:clean_字段名() 方法
def clean_name(self):
print("我看了源码,你应该会帮我执行这个方法!")
value = self.cleaned_data.get("name")
if "哒哒哒" in value:
raise ValidationError("不符合社会主义核心价值观!")
else:
return value
def clean_name(self):
print("我看了源码,你应该会帮我执行这个方法!")
value = self.cleaned_data.get("name")
if "哒哒哒" in value:
raise ValidationError("不符合社会主义核心价值观!")
else:
return value
三、全局钩子:重写clean()方法
校验两次密码是否一致
def clean(self):
print("我可是看过源码的人,我知道你肯定会执行这个方法!")
# 重写父类的clean方法
# 该clean方法, 在每个字段都校验通过之后才调用执行
pwd = self.cleaned_data.get("pwd")
re_pwd = self.cleaned_data.get("re_pwd")
if re_pwd and re_pwd == pwd:
# 确认密码和密码相同, 正常
return self.cleaned_data
else:
# 确认密码和密码不同
self.add_error('re_pwd', "两次密码不一致")
raise ValidationError("两次密码不一致")
形参
* 收集(单参数)(位置参数)
** 收集(键值对)(关键字参数)
实参
* 按(单值)打散
**按(键值对)打散
ok
来源:oschina
链接:https://my.oschina.net/u/4418647/blog/4084522