一.Django的Form组件主要的几大功能:
1.生成HTML标签
2.验证用户数据(显示错误信息)
3.HTML Form提交保留上次提交数据
4.初始化页面显示内容
二.Form组件使用方法
1.创建类
2.创建字段(为了验证包含正则表达式)
3.当用户提交数据验证用户输入:
obj = Form(request.POST,request.FILES) #提交数据封装在request.POST,上传文件封装在request.FILES if obj.is_valid(): #is_valid做验证判断是否合法 obj.cleaned_data #正确在cleaned_data else: obj.errors #错误在errors
4.clean_字段:clean_开头的字段名单字段(对当前username字段验证)
5.clean() _post_clean() :对整体错误验证
三.初识Form组件
1.利用Form的功能使用给数据库添加编辑数据[生成HTML标签,验证用户数据(显示数据信息)]
(1)创建数据表:django_formapp1models.py
from django.db import models class UserInfo(models.Model): username = models.CharField(max_length=32) email = models.EmailField(max_length=32)
(2)主页面:django_form emplatesusers.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>主页面</title> </head> <body> <a href="/add_user/">添加</a> <ul> {% for row in user_list %} <li>{{ row.id }}-{{ row.username }}-{{ row.email }} <a href="/edit_user-{{ row.id }}/">编辑</a></li> {% endfor %} </ul> </body> </html>
(3)添加数据页面:django_form emplatesadd_user.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>插入提交页面</title> </head> <body> <form action="/add_user/" method="post" novalidate enctype="multipart/form-data"> {% csrf_token %} <p>{{ obj.username.label }} {{ obj.username }}{{ obj.errors.username.0 }}</p> {#obj.username是生成的HTML,obj.errors拿到错误信息.0拿到第一个#} <p>{{ obj.email.label }} {{ obj.email }}{{ obj.errors.email.0 }}</p> <input type="submit" value="提交" /> </form> </body> </html>
(4)编辑数据页面:django_form emplatesedit_user.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>编辑提交页面</title> </head> <body> <form action="/edit_user-{{ nid }}/" method="POST" novalidate> {#提交后id在GET上提交过去,其它的在POST里提交过去了#} {% csrf_token %} <p>{{ obj.username }}{{ obj.errors.username.0 }}</p> {#obj.username是生成的HTML,obj.errors.username拿到错误信息.0拿到第一个#} <p>{{ obj.email }}{{ obj.errors.email.0 }}</p> <input type="submit" value="提交" /> </form> </body> </html>
(5)URL配置:django_formdjango_formurls.py
from django.conf.urls import url from django.contrib import admin from app1 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^users/', views.users), #主页 url(r'^add_user/', views.add_user), #添加 url(r'^edit_user-(d+)/', views.edit_user), #编辑 ]
(6)from配置:django_formapp1forms.py
from django import forms as dforms #form组件 from django.forms import fields class UserForm(dforms.Form): #创建UserForm生成对话框类继承dforms.Form username = fields.CharField( #创建用户名生成input框(username名字跟创建数据库字段名一样) max_length=18, #最大18位 min_length=6, #最小6位 required=True, #是否必填 label='用户名:', error_messages={'required': '用户名不能为空', 'max_length': '太', 'min_length': '短', 'invalid': '名字格式不对'} #错误提示 ) email = fields.EmailField( #创建email生成input框 label='邮箱:', required=True, min_length=8, error_messages={'required': '邮箱不能为空', 'min_length': '太短了', 'invalid': '邮箱格式不对'} )
(6)函数配置:django_formapp1views.py
from django.shortcuts import render from django.shortcuts import redirect from app1 import models #主页 def users(request): user_list = models.UserInfo.objects.all() return render(request,'users.html',{'user_list':user_list}) #生成输入对话框和添加数据加验证 from app1.forms import UserForm def add_user(request): if request.method == 'GET': #以GET请求自动生成HTML obj = UserForm() #创建obj对象(当前obj没有内容只是input对话框) return render(request,'add_user.html',{'obj':obj}) #传到前端 else: obj = UserForm(request.POST,request.FILES) #UserForm是一个一个的对应关系,对应关系里对应的一大堆正则表达式,验证用户发来的数据,用户发来的数据全在request.POST,用户提交的文件在request.FILES if obj.is_valid(): #用户发来的数据是否全部验证成功 models.UserInfo.objects.create(**obj.cleaned_data) #把提交来的数据添加到数据库(cleaned_data把数据都获取好) return redirect('/users/') # else: return render(request, 'add_user.html', {'obj': obj}) #返回错误信息给前端 #编辑数据 def edit_user(request,nid): if request.method == "GET": #以GET请求自动生成HTML data = models.UserInfo.objects.filter(id=nid).first() #获取当前要编辑的对象 obj = UserForm({'username':data.username,'email':data.email}) #UserForm是保留要编辑的username和email字段给前端显示 return render(request,'edit_user.html',{'obj':obj,'nid':nid}) else: #接收修改的数据 obj = UserForm(request.POST) #UserForm是一个一个的对应关系,对应关系里对应的一大堆正则表达式,验证用户发来的数据,用户发来的数据全在request.POST if obj.is_valid(): #用户发来的数据是否全部验证成功 models.UserInfo.objects.filter(id=nid).update(**obj.cleaned_data) #更新要修改的数据库数据 return redirect('/users/') else: return render(request,'edit_user.html',{'obj':obj,'nid':nid})
访问:http://127.0.0.1:8080/users/点击添加xixixi和xixi18@qq.com:
+----+----------+-----------------+ | id | username | email | +----+----------+-----------------+ | 1 | xixixi | xixi18@qq.com | +----+----------+-----------------+
四.Form类
1.创建Form类时,主要涉及到字段和插件,字段用于对用户请求数据的验证,插件用于自动生成HTML
2.Django常用的内置字段(用于对用户请求数据的验证),用于保存正则表达式
(1)URL:django_formdjango_formurls.py
from django.conf.urls import url from django.contrib import admin from app1 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^add_user/', views.add_user), #添加 ]
(2)forms配置:django_formapp1forms.py
from django import forms as dforms from django.forms import fields #创建UserForm生成对话框类继承dforms.Form) class UserForm(dforms.Form): #CharField:字符串,一般都在创建时写入max_length参数 username = fields.CharField( #创建用户名生成input框 max_length=18, #最大18位 min_length=6, #最小6位 required=True, #是否必填 label='用户名:', #生成label标签或显示内容 # initial='请输入用户名', #设置默认值 # show_hidden_initial=False, #是否在当前插件后面再加一个隐藏的且具有默认值的插件(可用于检验两次输入是否一直) # disabled=True, #不可编辑 error_messages={'required': '用户名不能为空', 'max_length': '太', 'min_length': '短', 'invalid': '名字格式不对'} # 错误提示 ) #EmailField:字符串,会检查是否是合法的email地址 email = fields.EmailField( label='邮箱:', required=True, min_length=8, error_messages={'required': '邮箱不能为空', 'min_length': '太短了', 'invalid': '邮箱格式不对'} ) #IntegerField:[-2147483648,2147483647]的取值范围对Django所支持的数据库都是安全的 age = fields.IntegerField( label='年龄:', max_value=99, #最大值 min_value=18, #最小值 error_messages={ 'max_value': '太大了' } ) #FileField提交文件选择框 img = fields.FileField() #下拉框:TypedChoiceField city = fields.TypedChoiceField( coerce=lambda x: int(x), #把传的字符串转换成整型 choices=[(1, '上海',), (2, '北京'), (3, '香港'), ], #数据源 initial=2 #默认值北京 ) #多选框:MultipleChoiceField bobby = fields.MultipleChoiceField( #多选框 choices=[(1, '吃饭'), (2, '睡觉'), (3, '打豆豆')], #数据源 initial=[1, 3] #默认值吃饭,打豆豆 )
(4)函数:django_formapp1views.py
from django.shortcuts import render #生成输入对话框和添加数据加验证 from app1.forms import UserForm def add_user(request): if request.method == 'GET': #以GET请求自动生成HTML obj = UserForm() #创建obj对象(当前obj没有内容只是input对话框) return render(request,'add_user.html',{'obj':obj}) #传到前端 else: obj = UserForm(request.POST,request.FILES) #UserForm是一个一个的对应关系,对应关系里对应的一大堆正则表达式,验证用户发来的数据,用户发来的数据全在request.POST,用户提交的文件在request.FILES obj.is_valid() #用户发来的数据是否全部验证成功 print(obj.cleaned_data) #{'age': 18, 'bobby': ['1', '3'], 'city': 2, 'email': '113194773@qq.com', 'img': <InMemoryUploadedFile: 笔记.txt (text/plain)>, 'username': '西西西西西西西西'}
return render(request, 'add_user.html', {'obj': obj})
(5)页面:django_form emplatesadd_user.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>插入提交页面</title> </head> <body> <form action="/add_user/" method="post" novalidate enctype="multipart/form-data"> {% csrf_token %} <p>{{ obj.username.label }} {{ obj.username }}{{ obj.errors.username.0 }}</p> {#obj.username是生成的HTML,obj.errors拿到错误信息.0拿到第一个#} <p>{{ obj.age.label }} {{ obj.age }}{{ obj.errors.age.0 }}</p> {#age#} <p>{{ obj.email.label }} {{ obj.email }}{{ obj.errors.email.0 }}</p> {#email#} <p>{{ obj.img.label }}{{ obj.img }}</p> {#文件上传#} <p>{{ obj.city.label }}{{ obj.city }}</p> {#下拉框#} <p>{{ obj.bobby.label }}{{ obj.bobby }}</p> {#多选框#} <input type="submit" value="提交" /> </form> </body> </html>
访问:http://127.0.0.1:8080/add_user显示
3.Django常用选择插件,用于生成HTML标签
(1)forms配置:django_formapp1forms.py
from django.conf.urls import url from django.contrib import admin from app1 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^add_user/', views.add_user), #添加 ]
(2)forms配置:django_formapp1forms.py
from django import forms as dforms from django.forms import fields from django.forms import widgets class UserForm(dforms.Form): #创建UserForm生成对话框类继承dforms.Form) #单radio(值为字符串)方式一: radio = fields.CharField( widget=widgets.Select(choices=[(1, '吃饭'), (2, '睡觉'), (3, '打豆豆')]) #widget定制生成的单选框对话框 ) #单radio(值为字符串)方式二: radio2 = fields.ChoiceField( choices=[(1, '吃饭'), (2, '睡觉'), (3, '打豆豆')] ) #单select(值为字符串)方式一: select = fields.CharField( initial=2, widget=widgets.Select(choices=((1,'上海'),(2,'北京'),)) #widget定制生成的Select对话框 ) #单select(值为字符串)方式二 select2 = fields.ChoiceField( choices=((1, '上海'), (2, '北京'),), initial=2, widget=widgets.Select ) #单checkbox check_box= fields.CharField( #单选框 widget=widgets.CheckboxInput() ) #多选checkbox2 check_box2 = fields.MultipleChoiceField( #多选框方式1 initial=[2, ], #默认选北京 choices=((1, '上海'), (2, '北京'),), #数据源 widget=widgets.CheckboxSelectMultiple ) #多选checkbox3值为列表 check_box3 = fields.ChoiceField( #多选框方式2,值为列表 choices=((1, '上海'), (2, '北京'), (3, '北京1'),), #数据源 initial=2, #默认选北京 widget=widgets.RadioSelect )
(3)函数:django_formapp1views.py
from django.shortcuts import render #生成输入对话框和添加数据加验证 from app1.forms import UserForm def add_user(request): if request.method == 'GET': #以GET请求自动生成HTML obj = UserForm() #创建obj对象(当前obj没有内容只是input对话框) return render(request,'add_user.html',{'obj':obj}) #传到前端 else: obj = UserForm(request.POST,request.FILES) #UserForm是一个一个的对应关系,对应关系里对应的一大堆正则表达式,验证用户发来的数据,用户发来的数据全在request.POST,用户提交的文件在request.FILES obj.is_valid() #用户发来的数据是否全部验证成功 print(obj.cleaned_data) #{'check_box': 'False', 'check_box2': ['2'], 'select2': '2', 'check_box3': '2', 'radio2': '1', 'select': '2', 'radio': '1'} return render(request, 'add_user.html', {'obj': obj})
(4)页面:django_form emplatesadd_user.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>插入提交页面</title> </head> <body> <form action="/add_user/" method="post" novalidate enctype="multipart/form-data"> {% csrf_token %} <p>{{ obj.radio.label }}{{ obj.radio }}</p> <p>{{ obj.radio2.label }}{{ obj.radio2 }}</p> <p>{{ obj.select.label }}{{ obj.select }}</p> <p>{{ obj.select2.label }}{{ obj.select2 }}</p> <p>{{ obj.check_box.label }}{{ obj.check_box }}</p> <p>{{ obj.check_box2.label }}{{ obj.check_box2 }}</p> <p>{{ obj.check_box3.label }}{{ obj.check_box3 }}</p> <input type="submit" value="提交" /> </form> </body> </html>
访问:http://127.0.0.1:8080/add_user显示
五.自定义构造方法对于数据源进行实时更新
在使用选择标签时,需要注意choices的选项可以从数据库中获取,但是由于是静态字段 获取的值无法实时更新,那么需要自定义构造方法从而达到此目的。
1.对于下拉框或者数据源进行实时更新可以通过自定制的init实现
(1)数据库:django_formapp1models.py
from django.db import models class UserInfo(models.Model): username = models.CharField(max_length=32) email = models.EmailField(max_length=32)
(2)django_formdjango_formurls.py
from django.conf.urls import url from django.contrib import admin from app1 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^add_user/', views.add_user), #添加 ]
(3)主页:django_form emplatesadd_user.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>超市</h1> <p>价格:{{ obj.price }}</p> <p>水果:{{ obj.user_id }}</p> </body> </html>
(4)函数:django_formapp1views.py
from django.shortcuts import render from django import forms from django.forms import fields from django.forms import widgets from app1 import models class user(forms.Form): price = fields.IntegerField() #price价格:静态字段 user_id = fields.IntegerField( #user_id多选框 #widget=widgets.Select(choices=[(0,'香蕉'),(1,'苹果'),(2,'草莓'),]) widget=widgets.Select() # ) def __init__(self,*args,**kwargs): #第二步:只要创建user对象后__init__初始化执行一遍 super(user,self).__init__(*args,**kwargs) #第三步:拷贝所有的静态字段,赋值给self.fields self.fields['user_id'].widget.choices = models.UserInfo.objects.values_list('id', 'username') #第四步:取到self.fields,里面有user_id,里面有插件widget,在里面有choices(数据库取出新的数据) def add_user(request): obj = user() #第一步:当页面刷新创建user对象 return render(request,'add_user.html',{'obj':obj})
访问:http://127.0.0.1:8080/add_user/
六.validators自定义验证规则
1.Form组件扩展:
1)简单扩展:利用Form组件自带的正则扩展获取错误信息
自定制方式一:
from django.forms import Form from django.forms import widgets from django.forms import fields from django.core.validators import RegexValidator class MyForm(Form): user = fields.CharField( #CharField是字符串 error_messages={'invalid': '...'}, validators=[RegexValidator(r'^[0-9]+$', '请输入数字'), RegexValidator(r'^159[0-9]+$', '数字必须以159开头')], #自定义两个正则表达式验证(RegexValidator传俩参数放到validators里,第一个参数是正则表达式,第二个参数是错误提示) )
自定义方式二:
from django.forms import Form from django.forms import widgets from django.forms import fields from django.core.validators import RegexValidator class MyForm(Form): user = fields.RegexField(r'^[0-9]+$',error_messages={'invalid': '...'}) #只能写一个正则表达式验证
2)基于源码流程
a.clean开头的字段名单字段(对当前username字段验证)
(1)数据库:django_formapp1models.py
from django.db import models class UserInfo(models.Model): username = models.CharField(max_length=32) email = models.EmailField(max_length=32)
(2)django_formdjango_formurls.py
from django.conf.urls import url from django.contrib import admin from app1 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^ajax/', views.ajax), #验证主页 ]
(3)函数:django_formapp1views.py
from django.shortcuts import render from django import forms from django.forms import fields from django.shortcuts import HttpResponse from django.forms import widgets from app1 import models from django.core.exceptions import NON_FIELD_ERRORS, ValidationError # ValidationError返回错误信息模块 class AjaxForm(forms.Form): username = fields.CharField() #第一步:第一个字段进来先验证username正则表达式 user_id = fields.IntegerField( #第三步:第二个字段进来验证user_id正则表达式 widget=widgets.Select(choices=[(0, '东东'), (1, '南南'), (2, '北北'), ]) ) #自定义方法clean_字段名 def clean_username(self): #第二步:如果正则表达式通过执行自定义clean_username方法 v = self.cleaned_data['username'] #必须有返回值,返回值self.cleaned_data['username']赋值给v if models.UserInfo.objects.filter(username=v).count(): #去数据库比对(某一个字段错了,整体就错了,自己的详细错误信息要有) raise ValidationError('用户名已存在') #如果出错:raise ValidationError('用户名已存在') return v #如果没出错把正确的值返回给用户(v=self.cleaned_data) def clean_user_id(self): #第四步:如果正则表达式通过执行自定义clean_user_id方法 return self.cleaned_data['user_id'] def ajax(request): if request.method == 'GET': obj = AjaxForm() return render(request,'ajax.html',{'obj':obj}) else: ret = {'status': '错误', 'message': None} # 定义默认信息 import json obj = AjaxForm(request.POST) # 准备做验证 if obj.is_valid(): # is_valid做验证判断是否合法 ret['status'] = '西' # 验证成功 return HttpResponse(json.dumps(ret)) # 返回json数据到前端 else: ret['message'] = obj.errors # 失败把错误信息返回给前端 # 错误信息显示在页面上 return HttpResponse(json.dumps(ret))
(4)主页面:django_form emplatesajax.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form id="fm" method="POST" action="/ajax/"> {% csrf_token %} {{ obj.as_p }} <input type="button" value="Ajax提交" id="btn" /> </form> <script src="/static/jquery-3.1.1.js"></script> <script> $(function () { $('#btn').click(function () { $.ajax({ url: '/ajax/', type: 'POST', data: $('#fm').serialize(), dataType: 'JSON', success:function (arg) { if (arg.status == '西'){ //arg包括后台处理的状态和错误信息 window.location.href = "http://www.baidu.com" } console.log(arg); } }) }) }) </script> </body> </html>
访问如果数据库有草莓不跳转:http://127.0.0.1:8080/ajax/
b.clean方法对整体错误验证
(1)django_formdjango_formurls.py
from django.conf.urls import url
from django.contrib import admin
from app1 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^ajax/', views.ajax), #验证主页
]
(2)函数:django_formapp1views.py
from django.shortcuts import render from django.shortcuts import HttpResponse from django import forms from django.forms import fields from django.forms import widgets from django.core.exceptions import NON_FIELD_ERRORS, ValidationError # ValidationError返回错误信息模块 class AjaxForm(forms.Form): username = fields.CharField() user_id = fields.IntegerField( widget=widgets.Select(choices=[(0, '东东'), (1, '南南'), (2, '北北'), ]) ) def clean(self): value_dict = self.cleaned_data #把用户名密码获取到做验证 v1 = value_dict.get('username') #做验证 v2 = value_dict.get('user_id') #做验证 if v1 == 'root' and v2 == 1: #如果v1等于root,v2等于1(模拟从数据库获取) raise ValidationError('整体错误信息') return self.cleaned_data # def ajax(request): if request.method == 'GET': obj = AjaxForm() return render(request,'ajax.html',{'obj':obj}) else: ret = {'status':'错误','message':None} #定义默认信息 import json obj = AjaxForm(request.POST) #准备做验证 if obj.is_valid(): #is_valid做验证判断是否合法 ret['status'] = '西' #验证成功 return HttpResponse(json.dumps(ret)) #返回json数据到前端 else: ret['message'] = obj.errors #失败把错误信息返回给前端 #错误信息显示在页面上 return HttpResponse(json.dumps(ret))
(3)主页面:django_form emplatesajax.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form id="fm" method="POST" action="/ajax/"> {% csrf_token %} {{ obj.as_p }} <input type="button" value="Ajax提交" id="btn" /> </form> <script src="/static/jquery-3.1.1.js"></script> <script> $(function () { $('#btn').click(function () { $.ajax({ url: '/ajax/', type: 'POST', data: $('#fm').serialize(), dataType: 'JSON', success:function (arg) { if (arg.status == '西'){ //arg包括后台处理的状态和错误信息 window.location.href = "http://www.baidu.com" } console.log(arg); } }) }) }) </script> </body> </html>
访问输入用户名root,id为1的南南无法跳转:http://127.0.0.1:8080/ajax/