form介绍
form组件的主要功能:
1、生成可用的html标签
2、对用户提交的数据进行效验
3、保留上次输入的内容
1、以普通方式手写注册功能
1、渲染前端标签获取用户输入 》》》》渲染标签
2、获取用户输入传递到后端效验》》》效验数据(可以做前端效验,也可以后端效验,前端可以不做,后端必须做)
3、效验未通过展示错误信息》》》展示信息
#urls.py
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^register/',views.register)
]
# views.py # 注册 def register(request): errors = {'username':'','password':''} if request.method == 'POST': username=request.POST.get('username') password=request.POST.get('password') if 'sb' in username: errors['username'] = '用户名中不能有关键值dsb' if '123' in password: errors['password'] = '密码中不能有123' return render(request,'register.html',locals())
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>注册</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"> </head> <body> <h1>注册页面</h1> <form action="" method="post"> <p>用户名: <input type="text" name="username"> <span>{{ errors.username }}</span> </p> <p>密码: <input type="text" name="password"> <span>{{ errors.password }}</span> </p> <input type="submit"> </form> </body> </html>
2、使用django中form组件实现注册功能
渲染标签
效验数据
展示信息
先定义好一个regform类:
# 效验数据 第一步先定义一个form类 from django import forms class regform(forms.Form): name=forms.CharField(max_length=6) password=forms.CharField(max_length=8,min_length=3) email= forms.EmailField(required=True) 第二步实例化form对象 form_obj=regform({‘name’:'jason','password':'123','email':'test@163.com'}) 第三部查看数据效验是否合法 form_obj.is_valid() #返回true或false;只有当所有的字段都效验通过才会返回True 第四步查看效验错误的信息 from_obj.errors #这个里面放的是所有效验未通过的字段及错误提示信息 第五步查看效验通过的数据 form_obj.cleaned_data #符合效验规则数据都会被放到该对象中 备注:form组件效验数据的规则从上往下有一次取值效验 效验通过的放到cleaned_data 效验失败的放到errors form中所有的字段默认都必须传值的(required=True) 效验的时候可以多传值,多传的值不会效验,没有影响
form组件渲染标签:
# views.py from django import forms class regform(forms.Form): name=forms.CharField(max_length=6) password=forms.CharField(max_length=8,min_length=3) email= forms.EmailField(required=True) def reg(request): # 生成一个空对象 form_obj=regform() return render(request,'reg.html',locals())
# reg.html <h1>第一种渲染方式</h1> {{ form_obj.as_p }} {{ form_obj.as_ul }}
<h1>第二种渲染方式</h1> {{ form_obj.name }} {{ form_obj.password }} {{ form_obj.email }}
这种方式只显示三个空可以设置标签显示框名字:
# 这里设置label标签调用后端定义的label标签,如果没有定义默认查找定义的名字 <h1>第二种渲染方式</h1> <p>{{ form_obj.name.label }}{{ form_obj.name }}</p> <p>{{ form_obj.password.label }}{{ form_obj.password }}</p> <p>{{ form_obj.email.label }}{{ form_obj.email }}</p>
from django import forms class regform(forms.Form): name=forms.CharField(max_length=6) password=forms.CharField(max_length=8,min_length=3) email= forms.EmailField(required=True) def reg(request): # 生成一个空对象 form_obj=regform() return render(request,'reg.html',locals())
网页显示首字母大写
设置标签后
from django import forms class regform(forms.Form): name=forms.CharField(max_length=6,label='用户名') password=forms.CharField(max_length=8,min_length=3,label='密码') email= forms.EmailField(required=True,label='邮箱') def reg(request): # 生成一个空对象 form_obj=regform() return render(request,'reg.html',locals())
渲染标签:
form组件只帮你渲染获取用户输入的标签,不会帮你渲染提交按钮,提交按钮需要手动添加
第三种渲染方法:
<h1>第三种渲染方式</h1>
<form action="" method="post">
{% for foo in form_obj %}
<p>{{ foo.label }}{{ foo }}</p>
{% endfor %}
<input type="submit">
# views # 后端判断输入数据是否合法,合法前台提交返回ok,不合法会保留之前用户输入的信息 from django import forms class regform(forms.Form): name=forms.CharField(max_length=6,label='用户名') password=forms.CharField(max_length=8,min_length=3,label='密码') email= forms.EmailField(required=True,label='邮箱') def reg(request): # 生成一个空对象 form_obj=regform() if request.method=='POST': print(request.POST) form_obj=regform(request.POST) if form_obj.is_valid(): # 合法返回true,不合法返回false return HttpResponse('ok') return render(request,'reg.html',locals())
在输入框后面显示提示字符:
<h1>第三种渲染方式</h1> <form action="" method="post" novalidate> {% for foo in form_obj %} <p>{{ foo.label }}{{ foo }}<span>{{ foo.errors.0 }}</span></p> {% endfor %} <input type="submit">
输入框内信息不合法,默认显示英文信息
提示信息显示中文:(修改创建的类)
# 设置error_message字典,里面填写错误信息
from django import forms class regform(forms.Form): name=forms.CharField(max_length=6,label='用户名',error_messages={'max_length':'用户最长6位','required':'用户名不能为空'}) password=forms.CharField(max_length=8,min_length=3,label='密码') email= forms.EmailField(required=True,label='邮箱') def reg(request): # 生成一个空对象 form_obj=regform() if request.method=='POST': print(request.POST) form_obj=regform(request.POST) if form_obj.is_valid(): return HttpResponse('ok') return render(request,'reg.html',locals())
from django import forms class regform(forms.Form): name=forms.CharField(max_length=6,label='用户名',error_messages={'max_length':'用户最长6位','required':'用户名不能为空'}) password=forms.CharField(max_length=8,min_length=3,label='密码',error_messages={'max_length':'密码最长6位','min_length':'密码最短3位','required':'密码不能为空'}) email= forms.EmailField(required=True,label='邮箱',error_messages={'invalid':'邮箱格式不正确','required':'邮箱不能为空'}) def reg(request): # 生成一个空对象 form_obj=regform() if request.method=='POST': print(request.POST) form_obj=regform(request.POST) if form_obj.is_valid(): return HttpResponse('ok') return render(request,'reg.html',locals())
使用form组件对模型表进行数据效验的时候,只需要保证字段一致,在创建对象的时候直接**form_obj.cleaned_data
from app01 import models from django import forms class regform(forms.Form): name=forms.CharField(max_length=6,label='用户名',error_messages={'max_length':'用户最长6位','required':'用户名不能为空'}) password=forms.CharField(max_length=8,min_length=3,label='密码',error_messages={'max_length':'密码最长6位','min_length':'密码最短3位','required':'密码不能为空'}) email= forms.EmailField(required=True,label='邮箱',error_messages={'invalid':'邮箱格式不正确','required':'邮箱不能为空'}) def reg(request): # 生成一个空对象 form_obj=regform() if request.method=='POST': print(request.POST) form_obj=regform(request.POST) if form_obj.is_valid(): print(form_obj.cleaned_data) models.User.object.create(**form_obj.cleaned_data) return render(request,'reg.html',locals())
钩子函数
局部钩子杉树(单个字段的效验利用局部钩子函数)
from app01 import models
from django import forms
class regform(forms.Form):
name=forms.CharField(max_length=6,label='用户名',error_messages={'max_length':'用户最长6位','required':'用户名不能为空'})
password=forms.CharField(max_length=8,min_length=3,label='密码',error_messages={'max_length':'密码最长6位','min_length':'密码最短3位','required':'密码不能为空'})
email= forms.EmailField(required=True,label='邮箱',error_messages={'invalid':'邮箱格式不正确','required':'邮箱不能为空'})
def clean_name(self):
name=self.cleaned_data.get('name')
if '6' in name:
self.add_error('name','不能包含6字符')
return name
def reg(request):
# 生成一个空对象
form_obj=regform()
if request.method=='POST':
print(request.POST)
form_obj=regform(request.POST)
if form_obj.is_valid():
print(form_obj.cleaned_data)
models.User.object.create(**request.POST)
return render(request,'reg.html',locals())
全局钩子函数(多个字段效验利用全局钩子函数)(效验多个字段)
from app01 import models from django import forms class regform(forms.Form): name=forms.CharField(max_length=6,label='用户名',error_messages={'max_length':'用户最长6位','required':'用户名不能为空'}) password=forms.CharField(max_length=8,min_length=3,label='密码',error_messages={'max_length':'密码最长6位','min_length':'密码最短3位','required':'密码不能为空'}) re_password=forms.CharField(max_length=8,min_length=3,label='密码',error_messages={'max_length':'密码最长6位','min_length':'密码最短3位','required':'密码不能为空'}) email= forms.EmailField(required=True,label='邮箱',error_messages={'invalid':'邮箱格式不正确','required':'邮箱不能为空'}) def clean_name(self): name=self.cleaned_data.get('name') if '6' in name: self.add_error('name','不能包含6字符') return name def clean(self): password=self.cleaned_data.get('password') re_password=self.cleaned_data.get('re_password') if not password == re_password: self.add_error('re_password','重复输入密码不一致') return self.cleaned_data def reg(request): # 生成一个空对象 form_obj=regform() if request.method=='POST': print(request.POST) form_obj=regform(request.POST) if form_obj.is_valid(): print(form_obj.cleaned_data) models.User.object.create(**request.POST) return render(request,'reg.html',locals())
form密码框密码显示明文,设置密文,
from app01 import models from django import forms from django.forms import widgets class regform(forms.Form): name=forms.CharField(max_length=6,label='用户名',error_messages={'max_length':'用户最长6位','required':'用户名不能为空'}) password=forms.CharField(max_length=8,min_length=3,label='密码',error_messages={'max_length':'密码最长6位',
'min_length':'密码最短3位','required':'密码不能为空'},widget=widgets.PasswordInput()) re_password=forms.CharField(max_length=8,min_length=3,label='密码',error_messages={'max_length':'密码最长6位',
'min_length':'密码最短3位','required':'密码不能为空'}) email= forms.EmailField(required=True,label='邮箱',error_messages={'invalid':'邮箱格式不正确',
'required':'邮箱不能为空'}) def clean_name(self): name=self.cleaned_data.get('name') if '6' in name: self.add_error('name','不能包含6字符') return name def clean(self): password=self.cleaned_data.get('password') re_password=self.cleaned_data.get('re_password') if not password == re_password: self.add_error('re_password','重复输入密码不一致') return self.cleaned_data def reg(request): # 生成一个空对象 form_obj=regform() if request.method=='POST': print(request.POST) form_obj=regform(request.POST) if form_obj.is_valid(): print(form_obj.cleaned_data) models.User.object.create(**request.POST) return render(request,'reg.html',locals())
设置form框样式,设置标签样式
from app01 import models from django import forms from django.forms import widgets class regform(forms.Form): name=forms.CharField(max_length=6,label='用户名',error_messages={'max_length':'用户最长6位', 'required':'用户名不能为空'}) password=forms.CharField(max_length=8,min_length=3,label='密码',error_messages={'max_length':'密码最长6位', 'min_length':'密码最短3位', 'required':'密码不能为空'},widget=widgets.PasswordInput(attrs={'class': 'form-control'})) re_password=forms.CharField(max_length=8,min_length=3,label='密码',error_messages={'max_length':'密码最长6位', 'min_length':'密码最短3位', 'required':'密码不能为空'},widget=widgets.TextInput(attrs={'class':'form-control'})) email= forms.EmailField(required=True,label='邮箱',error_messages={'invalid':'邮箱格式不正确', 'required':'邮箱不能为空'}) def clean_name(self): name=self.cleaned_data.get('name') if '6' in name: self.add_error('name','不能包含6字符') return name def clean(self): password=self.cleaned_data.get('password') re_password=self.cleaned_data.get('re_password') if not password == re_password: self.add_error('re_password','重复输入密码不一致') return self.cleaned_data def reg(request): # 生成一个空对象 form_obj=regform() if request.method=='POST': print(request.POST) form_obj=regform(request.POST) if form_obj.is_valid(): print(form_obj.cleaned_data) models.User.object.create(**request.POST) return render(request,'reg.html',locals())
radioSelect
单radio值为字符串
class LoginForm(forms.Form): username = forms.CharField( min_length=8, label="用户名", initial="张三", error_messages={ "required": "不能为空", "invalid": "格式错误", "min_length": "用户名最短8位" } ) pwd = forms.CharField(min_length=6, label="密码") gender = forms.fields.ChoiceField( choices=((1, "男"), (2, "女"), (3, "保密")), label="性别", initial=3, widget=forms.widgets.RadioSelect() )
单选Select
class LoginForm(forms.Form): ... hobby = forms.ChoiceField( choices=((1, "篮球"), (2, "足球"), (3, "双色球"), ), label="爱好", initial=3, widget=forms.widgets.Select() )
多选Select
class LoginForm(forms.Form): ... hobby = forms.MultipleChoiceField( choices=((1, "篮球"), (2, "足球"), (3, "双色球"), ), label="爱好", initial=[1, 3], widget=forms.widgets.SelectMultiple() )
单选checkbox
class LoginForm(forms.Form): ... keep = forms.ChoiceField( label="是否记住密码", initial="checked", widget=forms.widgets.CheckboxInput() )
多选checkbox
class LoginForm(forms.Form): ... hobby = forms.MultipleChoiceField( choices=((1, "篮球"), (2, "足球"), (3, "双色球"),), label="爱好", initial=[1, 3], widget=forms.widgets.CheckboxSelectMultiple() )
django操作cookie,session
http协议四大特性
1.基于TCP/IP作用于应用层的协议
2.基于请求响应
3.无状态
4.无连接
cookie
保存在客户端浏览器上的键值对
session
保存在服务端上的键值对
服务端产生随机的串儿返回给客户端,服务端找一个地方将串儿与对应的信息存起来{'随机字符串':'敏感信息'}
设置cookies,登录账号后才可以查看index页面,没有登录访问index页面跳转到登录页面
def login(request): if request.method=='POST': username=request.POST.get('username') password=request.POST.get('password') if username=='yzn' and password=='123': obj=redirect('/index/') obj.set_cookie('name','test') return obj return render(request,'login.html') def index(request): if request.COOKIES.get('name'): return HttpResponse('我是index页面,只有登录才能查看') return redirect('/login/')
针对多个页面判断是都用户登录,用户没有登录不能查看页面
from app01 import models from django import forms from django.forms import widgets class regform(forms.Form): name=forms.CharField(max_length=6,label='用户名',error_messages={'max_length':'用户最长6位', 'required':'用户名不能为空'}) password=forms.CharField(max_length=8,min_length=3,label='密码',error_messages={'max_length':'密码最长6位', 'min_length':'密码最短3位', 'required':'密码不能为空'},widget=widgets.PasswordInput(attrs={'class': 'form-control'})) re_password=forms.CharField(max_length=8,min_length=3,label='密码',error_messages={'max_length':'密码最长6位', 'min_length':'密码最短3位', 'required':'密码不能为空'},widget=widgets.TextInput(attrs={'class':'form-control'})) email= forms.EmailField(required=True,label='邮箱',error_messages={'invalid':'邮箱格式不正确', 'required':'邮箱不能为空'}) def clean_name(self): name=self.cleaned_data.get('name') if '6' in name: self.add_error('name','不能包含6字符') return name def clean(self): password=self.cleaned_data.get('password') re_password=self.cleaned_data.get('re_password') if not password == re_password: self.add_error('re_password','重复输入密码不一致') return self.cleaned_data def reg(request): # 生成一个空对象 form_obj=regform() if request.method=='POST': print(request.POST) form_obj=regform(request.POST) if form_obj.is_valid(): print(form_obj.cleaned_data) models.User.object.create(**request.POST) return render(request,'reg.html',locals()) def login(request): if request.method=='POST': username=request.POST.get('username') password=request.POST.get('password') if username=='yzn' and password=='123': obj=redirect('/index/') obj.set_cookie('name','test') return obj return render(request,'login.html') from functools import wraps def login_auth(func): #设置装饰器 @wraps(func) def inner(request,*args,**kwargs): # 校验cookies if request.COOKIES.get('name'): return func(request,*args,**kwargs) return redirect('/login/') return inner @login_auth def index(request): return HttpResponse('我是index页面,只有登录才能查看') @login_auth def home(request): return HttpResponse('我是home页面,只有登录才可以查看')
用户没有登陆点击新的页面,跳转到登录页面,登录后返回原本想要访问的页面:
from app01 import models from django import forms from django.forms import widgets class regform(forms.Form): name=forms.CharField(max_length=6,label='用户名',error_messages={'max_length':'用户最长6位', 'required':'用户名不能为空'}) password=forms.CharField(max_length=8,min_length=3,label='密码',error_messages={'max_length':'密码最长6位', 'min_length':'密码最短3位', 'required':'密码不能为空'},widget=widgets.PasswordInput(attrs={'class': 'form-control'})) re_password=forms.CharField(max_length=8,min_length=3,label='密码',error_messages={'max_length':'密码最长6位', 'min_length':'密码最短3位', 'required':'密码不能为空'},widget=widgets.TextInput(attrs={'class':'form-control'})) email= forms.EmailField(required=True,label='邮箱',error_messages={'invalid':'邮箱格式不正确', 'required':'邮箱不能为空'}) def clean_name(self): name=self.cleaned_data.get('name') if '6' in name: self.add_error('name','不能包含6字符') return name def clean(self): password=self.cleaned_data.get('password') re_password=self.cleaned_data.get('re_password') if not password == re_password: self.add_error('re_password','重复输入密码不一致') return self.cleaned_data def reg(request): # 生成一个空对象 form_obj=regform() if request.method=='POST': print(request.POST) form_obj=regform(request.POST) if form_obj.is_valid(): print(form_obj.cleaned_data) models.User.object.create(**request.POST) return render(request,'reg.html',locals()) def login(request): if request.method=='POST': username=request.POST.get('username') password=request.POST.get('password') if username=='yzn' and password=='123': old_path=request.GET.get('next') #判断登录login的上一级页面 if old_path: #如果有上一级页面登录后直接返回上一级 obj=redirect(old_path) else: #登录成功后默认跳转页面 obj=redirect('/home/') obj.set_cookie('name','test') return obj return render(request,'login.html') from functools import wraps def login_auth(func): @wraps(func) def inner(request,*args,**kwargs): print(request.get_full_path()) old_path=request.get_full_path() #获取上一级目录路径 # 校验cookies if request.COOKIES.get('name'): return func(request,*args,**kwargs) return redirect('/login/?next=%s'%old_path) #在前端网址输入栏中显示上一级访问地址 return inner @login_auth def index(request): return HttpResponse('我是index页面,只有登录才能查看') @login_auth def home(request): return HttpResponse('我是home页面,只有登录才可以查看') @login_auth def test(request): return HttpResponse('我是test页面,只有登录才可以查看')
设置cookie的超时时间:
obj.set_cookie('name','test',expires=10) #设置cookie值,expries设置超时时间,默认是秒,支持*
- max_age=None, 超时时间
- expires=None, 超时时间(IE requires expires, so set it if hasn't been already.)
退出清除cookie
def logout(request): rep = redirect("/login/") rep.delete_cookie("user") # 删除用户浏览器上之前设置的usercookie值 return rep
设置session:
from functools import wraps def check_login(func): @wraps(func) def inner(request, *args, **kwargs): next_url = request.get_full_path() if request.session.get("user"): return func(request, *args, **kwargs) else: return redirect("/login/?next={}".format(next_url)) return inner def login(request): if request.method == "POST": user = request.POST.get("user") pwd = request.POST.get("pwd") if user == "alex" and pwd == "alex1234": # 设置session request.session["user"] = user # 获取跳到登陆页面之前的URL next_url = request.GET.get("next") # 如果有,就跳转回登陆之前的URL if next_url: return redirect(next_url) # 否则默认跳转到index页面 else: return redirect("/index/") return render(request, "login.html") @check_login def logout(request): # 删除所有当前请求相关的session request.session.delete() return redirect("/login/") @check_login def index(request): current_user = request.session.get("user", None) return render(request, "index.html", {"user": current_user})