一、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