先自己实现注册功能,并且对用户输入的信息加限制条件
如果用户输入的信息不符合条件,前端展示报错信息
1 from django.shortcuts import render,HttpResponse 2 3 4 from django.core.exceptions import ValidationError 5 # Create your views here. 6 7 8 9 def register(request): 10 errors = {‘name‘:‘‘, ‘pwd‘:‘‘} #定义一个字典,将字典传给前端,前端是可以取值的 11 if request.method == ‘POST‘: 12 name = request.POST.get(‘name‘) 13 pwd = request.POST.get(‘pwd‘) 14 if ‘sb‘ in name: 15 errors[‘name‘] =‘名字不能包含sb‘ 16 if pwd == ‘123‘: 17 errors[‘pwd‘] = ‘你这密码太简单了‘ 18 return render(request,‘reg.html‘,locals())
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 <h3>注册页面</h3> 9 10 <form action="" method="post"> 11 <p>username:<input type="text" name="name"> 12 <span>{{ errors.name }}</span> <!--span是行内标签,大小由文本决定的,如果取到的值为空前端展示到前端页面看不出--> 13 </p> 14 15 <p>password:<input type="text" name="pwd"> 16 <span>{{ errors.pwd }}</span></p> 17 <input type="submit"> 18 </form> 19 20 </body> 21 </html>
注意:reg.html中的
<span>{{ errors.name }}</span>
思路:访问路由,是get请求然后error字典中的value值为空,所以传入前端的error信息为空,
然后span标签是根据文本内容的大小来撑大,所以没有内容就不变,不会有什么影响,
第二次form表单提交的时候是有name和password的数据,
然后进行校验,如果不满足条件,就给error字典赋值传给前端,所以前端会显示错误信息
总结:
注册示例:
1.前端渲染标签获取用户输入 >>> 前端渲染标签
2.后端获取用户输入,进行数据校验 >>> 数据校验
3.校验过后产生的提示信息返回给前端 >>> 展示校验信息
提一小嘴:??♀?
数据校验:
前端后端都必须做数据校验,前端不做问题不大,后端必须要做!(防爬虫!!!) (提前low一眼哈哈哈)??????(前端浏览器会自动做校验)
form组件就能帮我们完成上面的三步:???
1.生成前端html代码
2.校验数据
3.展示校验信息
先上图看看前端的效果??
forms组件的使用??
1.简单的form组件校验数据
校验数据
1.得写一个forms校验的类
from django import forms
class RegForm(forms.Form):
# forms组件中定义的字段,默认都是必须传值的
name = forms.CharField(max_length=6)
pwd = forms.CharField(max_length=8,min_length=3)
email = forms.EmailField()
2.实例化RegForm传值
# 注意传入的字典的key必须跟类里面的变量名一致,校验的数据可以多传,但是不能少传
res = views.RegForm({‘name‘:‘dsb‘,‘pwd‘:‘123‘,‘email‘:‘123@qq.com‘})
3.数据是否合法
res.is_valid() # 如果数据全部校验通过才为True否则均为False
4.查看校验通过的数据
res.cleaned_data # 会将校验通过的数据都放入cleaned_data中
5.查看校验失败的数据
res.errors # 会将校验失败的数据的提示信息都放入errors中
"""
{
‘name‘: [‘Ensure this value has at most 6 characters (it has 7).‘],
‘pwd‘: [‘Ensure this value has at least 3 characters (it has 2).‘]
}
"""
几个图例看看更清楚哦??
??????????
??????
??????
??????
??????
渲染标签
form组件值渲染获取用户输入(或选择的...只要是用户操作都算)的标签
提交按钮需要我们自己手动写
三种方式:
1.{{ form_obj.as_p }}
2.{{ form_obj.name.label }}{{ form_obj.name }}
3.{% for foo in form_obj %}
<p>{{ foo.label }}{{ foo }}</p>
{% endfor %}
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 9 <p>第一种渲染方式(封装程度太高,没法做扩展,不推荐使用,了解即可)</p> 10 {{ form_obj.as_p }} <!--渲染成一个个p标签--> 11 {{ form_obj.ul }} <!--渲染成一个个ul标签--> 12 13 14 <p>第二种渲染方式</p> 15 <form action=""> 16 <p>{{ form_obj.name.label }}{{ form_obj.name }}</p> 17 <p>{{ form_obj.pwd.label }}{{ form_obj.pwd }}</p> 18 <p>{{ form_obj.email.label }}{{ form_obj.email }}</p> 19 <input type="submit"> 20 </form> 21 22 <p>第三种渲染方式</p> 23 <form action=""> 24 {% for foo in form_obj %} 25 <p>{{ foo.label }}{{ foo }}</p> 26 {% endfor %} 27 28 </form> 29 30 </body> 31 </html>
<!--渲染成一个个ul标签-->
{{ form_obj.ul }}
{{ form_obj.as_p }} <!--渲染成一个个p标签-->
<p>第二种渲染方式</p>
<form action="">
<p>{{ form_obj.name.label }}{{ form_obj.name }}</p>
<p>{{ form_obj.pwd.label }}{{ form_obj.pwd }}</p>
<p>{{ form_obj.email.label }}{{ form_obj.email }}</p>
<input type="submit">
</form>
<p>第三种渲染方式</p>
<form action="">
{% for foo in form_obj %}
<p>{{ foo.label }}{{ foo }}</p>
{% endfor %}
</form>
以下图片有误,是第三种渲染方式
展示报错信息??
<form action="" method="post" novalidate>
{% for foo in form_obj %}
<p>{{ foo.label }}{{ foo }}</p>
<span>{{ foo.errors.0 }}</span> <!--errors是多个参数,代表是多个参数,就用ul套li的形式展示出来,.0是取报错信息本身文本,而不是取我报错信息对象-->
{% endfor %}
<input type="submit">
</form>
#钩子函数
#局部钩子
#如想给name字段额外的校验, (会先从上往下走,三个字段将原本定义好的先校验一遍,再来走这个局部校验)
def clean_name(self):
name = self.cleaned_data.get(‘name‘)
if ‘666‘ in name:
#两种方式,手动添加
self.add_error(‘name‘,‘不能包含666‘)
# 抛异常
# raise ValidationError(‘不能包含666‘) #需要导入(在上头)from django.core.exceptions import ValidationError
else:
#拿出来校验的数据必须返回去
return name
#全局钩子 (将cleaned_data中的所有数据都交给你了,所以你做完校验之后都还给我,你不还给我就没了,再后面函数使用的时候就是空的)
#用于密码确认,
def clean(self):
pwd = self.cleaned_data.get(‘pwd‘)
confirm_pwd = self.cleaned_data.get(‘confirm_pwd‘)
if pwd == confirm_pwd:
return self.cleaned_data
else:
self.add_error(‘confirm_pwd‘,‘两次棉麻不一致‘) #全局要把报错信息加进去,不能使用抛异常的方法
总的代码过一遍
1 from django.shortcuts import render,HttpResponse 2 3 4 from django.core.exceptions import ValidationError 5 # Create your views here. 6 7 8 9 def register(request): 10 errors = {‘name‘:‘‘, ‘pwd‘:‘‘} #定义一个字典,将字典传给前端,前端是可以取值的 11 if request.method == ‘POST‘: 12 name = request.POST.get(‘name‘) 13 pwd = request.POST.get(‘pwd‘) 14 if ‘sb‘ in name: 15 errors[‘name‘] =‘名字不能包含sb‘ 16 if pwd == ‘123‘: 17 errors[‘pwd‘] = ‘你这密码太简单了‘ 18 return render(request,‘reg.html‘,locals()) 19 20 from django import forms 21 class RegForm(forms.Form): #forms校验三个字段属性,只要有一条不符合就返回false 22 #forms组件中定义的字段,默认都是必须传值的 23 name = forms.CharField(max_length=8,label=‘用户名‘,error_messages={ 24 ‘max_length‘:‘用户名最长只能6位‘, 25 ‘required‘:‘这个字段不能为空‘},widget=forms.TextInput()) #没写默认采用Name作为label 26 pwd = forms.CharField(max_length=8, min_length=3,error_messages={ 27 ‘max_length‘:‘密码最长8位‘, 28 ‘min_length‘:‘密码最短3位‘, 29 ‘required‘:‘密码这个字段不能为空‘, 30 #attrs={‘class‘:‘c1‘ ‘form-control‘} 修改样式:c1是input框继承的类 31 },widget=forms.widgets.PasswordInput(attrs={‘class‘:‘c1‘ ‘form-control‘})) #最小三位 widget=forms.widgets.PasswordInput()密码是密文显示 32 33 #注册还需要确认密码 34 confirm_pwd = forms.CharField(max_length=8, min_length=3, error_messages={ 35 ‘max_length‘: ‘密码最长8位‘, 36 ‘min_length‘: ‘密码最短3位‘, 37 ‘required‘: ‘密码这个字段不能为空‘, 38 # attrs={‘class‘:‘c1‘ ‘form-control‘} 修改样式:c1是input框继承的类 39 }, widget=forms.widgets.PasswordInput(attrs={‘class‘: ‘c1‘ ‘form-control‘})) 40 41 42 email = forms.EmailField(label=‘邮箱‘,error_messages={ 43 ‘invalid‘:‘邮箱格式不正确‘, 44 ‘required‘: ‘邮箱这个字段不能为空‘, 45 }) 46 47 gender = forms.ChoiceField( 48 choices=((1, ‘男‘), (2, ‘女‘),(3,‘保密‘)), 49 label = ‘性别‘, 50 initial = 3, 51 widget=forms.widgets.RadioSelect() 52 ) 53 54 #钩子函数 55 #局部钩子 56 #如想给name字段额外的校验, (会先从上往下走,三个字段将原本定义好的先校验一遍,再来走这个局部校验) 57 def clean_name(self): 58 name = self.cleaned_data.get(‘name‘) 59 if ‘666‘ in name: 60 #两种方式,手动添加 61 self.add_error(‘name‘,‘不能包含666‘) 62 # 抛异常 63 # raise ValidationError(‘不能包含666‘) #需要导入(在上头)from django.core.exceptions import ValidationError 64 else: 65 #拿出来校验的数据必须返回去 66 return name 67 #全局钩子 (将cleaned_data中的所有数据都交给你了,所以你做完校验之后都还给我,你不还给我就没了,再后面函数使用的时候就是空的) 68 #用于密码确认, 69 def clean(self): 70 pwd = self.cleaned_data.get(‘pwd‘) 71 confirm_pwd = self.cleaned_data.get(‘confirm_pwd‘) 72 if pwd == confirm_pwd: 73 return self.cleaned_data 74 else: 75 self.add_error(‘confirm_pwd‘,‘两次棉麻不一致‘) #全局要把报错信息加进去,不能使用抛异常的方法 76 77 78 def reg(request): 79 #实例化一个form对象 80 form_obj = RegForm() 81 return render(request, ‘reg1.html‘,locals()) 82 def reg2(request): 83 #实例化一个form对象 84 form_obj = RegForm() 85 if request.method == ‘POST‘: 86 print(request.POST) 87 # < QueryDict: {‘name‘: [‘dsb‘], ‘pwd‘: [‘123‘], ‘email‘: [‘123@qq.com‘]} > 88 form_obj = RegForm(request.POST) #因为是字典可以直接传给RegForm 89 #需要注意的是:前端的input name的属性必须跟form组件种的字段名一致 90 if form_obj.is_valid(): 91 return HttpResponse(‘ok‘) 92 return render(request, ‘reg2.html‘,locals()) 93 94 #第一次form_obj = RegForm实例化的时候没传值,没有做校验,所以给前端页面的是一个空字典,只有渲染页面的效果 95 #第二次 form_obj = RegForm(request.POST) ,POST请求来了有数据传输过来,进行校验,所以可以form_obj.is_valid() 96 from app01 import models 97 def reg3(request): 98 #实例化一个form对象 99 form_obj = RegForm() 100 if request.method == ‘POST‘: 101 print(request.POST) 102 # < QueryDict: {‘name‘: [‘dsb‘], ‘pwd‘: [‘123‘], ‘email‘: [‘123@qq.com‘]} > 103 form_obj = RegForm(request.POST) #因为是字典可以直接传给RegForm 104 #需要注意的是:前端的input name的属性必须跟form组件种的字段名一致 105 if form_obj.is_valid(): 106 models.User.objects.create(**form_obj.cleaned_data) #form配合models用,其实是为了models服务的,只是保存数据 107 return render(request, ‘reg2.html‘,locals())
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 <h3>注册页面</h3> 9 10 <form action="" method="post"> 11 <p>username:<input type="text" name="name"> 12 <span>{{ errors.name }}</span> <!--span是行内标签,大小由文本决定的,如果取到的值为空前端展示到前端页面看不出--> 13 </p> 14 15 <p>password:<input type="text" name="pwd"> 16 <span>{{ errors.pwd }}</span></p> 17 <input type="submit"> 18 </form> 19 20 </body> 21 </html>
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 9 <p>第一种渲染方式(封装程度太高,没法做扩展,不推荐使用,了解即可)</p> 10 {{ form_obj.as_p }} <!--渲染成一个个p标签--> 11 {{ form_obj.ul }} <!--渲染成一个个ul标签--> 12 13 14 <p>第二种渲染方式</p> 15 <form action=""> 16 <p>{{ form_obj.name.label }}{{ form_obj.name }}</p> 17 <p>{{ form_obj.pwd.label }}{{ form_obj.pwd }}</p> 18 <p>{{ form_obj.email.label }}{{ form_obj.email }}</p> 19 <input type="submit"> 20 </form> 21 22 <p>第三种渲染方式</p> 23 <form action=""> 24 {% for foo in form_obj %} 25 <p>{{ foo.label }}{{ foo }}</p> 26 {% endfor %} 27 28 </form> 29 30 </body> 31 </html>
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 <form action="" method="post" novalidate> 9 {% for foo in form_obj %} 10 <p>{{ foo.label }}{{ foo }}</p> 11 <span>{{ foo.errors.0 }}</span> <!--errors是多个参数,代表是多个参数,就用ul套li的形式展示出来,.0是取报错信息本身文本,而不是取我报错信息对象--> 12 {% endfor %} 13 <input type="submit"> 14 </form> 15 </body> 16 </html>
1 gender = forms.ChoiceField( 2 choices=((1, "男"), (2, "女"), (3, "保密")), 3 label="性别", 4 initial=3, 5 widget=forms.widgets.RadioSelect() 6 ) 7 hobby = forms.ChoiceField( 8 choices=((1, "篮球"), (2, "足球"), (3, "双色球"),), 9 label="爱好", 10 initial=3, 11 widget=forms.widgets.Select() 12 ) 13 hobby1 = forms.MultipleChoiceField( 14 choices=((1, "篮球"), (2, "足球"), (3, "双色球"),), 15 label="爱好", 16 initial=[1, 3], 17 widget=forms.widgets.SelectMultiple() 18 ) 19 keep = forms.ChoiceField( 20 label="是否记住密码", 21 initial="checked", 22 widget=forms.widgets.CheckboxInput() 23 ) 24 hobby2 = forms.MultipleChoiceField( 25 choices=((1, "篮球"), (2, "足球"), (3, "双色球"),), 26 label="爱好", 27 initial=[1, 3], 28 widget=forms.widgets.CheckboxSelectMultiple() 29 )
本质:保存在浏览器上的键值对
用途:标识当前用户信息
cookie是服务端设置的,浏览器可以选择禁用
设置Cookie
问题:django返回的信息都是什么对象?
HttpResponse对象
return render()
return HttpResponse()
return redirect()
res1 = render()
return res1
res2 = HttpResponse()
return res2
res3 = redirect()
return res3
设置Cookie
需要通过HttpResponse对象来设值
res1 = render()
res1.set_cookie(‘name‘,‘jason‘)
return res1
获取Cookie
request.COOKIES[‘key‘]
request.COOKIES.get(‘key‘)
本质:保存在服务器上的键值对
用途:记录当前用户信息
session其实也是基于cookie工作的
为了数据更加安全,给浏览器存一个随机字符串,将用户信息存在服务端,
sessionid:‘随机字符串‘
用户在访问的时候,拿着这个随机字符串来后端进行匹配
设置Session (django 默认的session过期时间是14天)
request.session[‘k1‘] = 123
# 上面这句话干了三件事
# 1.内部自动生成一个随机字符串 一个浏览器对应一个
# 2.将随机字符串与数据字典存入django session表中
# 3.将随机字符串设置到浏览器的cookie中
获取session
request.session.get(‘k1‘)
# 浏览器将随机字符串发送给服务端之后,服务端自动拿着随机字符串去
# django_session表查找改字符串所对应的value(大字典),如果匹配成功会将这个value赋值给request.session
# 如果没有,说明当前用户没有进行身份认证.建议使用request.session.get()来获取大字典
删除session
# 删除当前会话的所有Session数据
request.session.delete() # 只删django_session表里的数据
# 删除当前的会话数据并删除会话的Cookie。
request.session.flush() # 表和浏览器的session都删除
这用于确保前面的会话数据不可以再次被用户的浏览器访问
例如,django.contrib.auth.logout() 函数中就会调用它。
# 设置会话Session和Cookie的超时时间
request.session.set_expiry(value) # value值同cookie设置超时时间
* 如果value是个整数,session会在些秒数后失效。
* 如果value是个datatime或timedelta,session就会在这个时间后失效。
* 如果value是0,用户关闭浏览器session就会失效。
* 如果value是None,session会依赖全局session失效策略。
session数据是存放在服务器端的数据库中
数据库可以有多种选择
Cookie和Session??
http协议不保存用户状态(信息)
Cookie和Session都是为了能够保存用户信息
1 from django.shortcuts import render,HttpResponse,redirect 2 3 # Create your views here. 4 5 from functools import wraps 6 def login_auth(func): 7 @wraps(func) 8 def inner(request,*args, **kwargs): 9 path = request.get_full_path() 10 print(path) 11 if request.COOKIES.get(‘name‘): 12 return func(request, *args, **kwargs) 13 else: 14 return redirect(‘/login?next=%s‘%path) 15 return inner 16 17 18 19 @login_auth 20 def login(request): 21 if request.method == ‘POST‘: 22 username = request.POST.get(‘username‘) 23 password = request.POST.get(‘password‘) 24 if username == ‘egon‘ and password == ‘123‘: 25 old_path = request.GET.get(‘next‘) 26 if old_path: 27 obj = redirect(old_path) 28 else: 29 obj = redirect(‘/index‘) 30 obj.set_cookie(‘name‘,‘egon‘,max_age=1) 31 return obj 32 return render(request, ‘login.html‘) 33 34 @login_auth 35 def index(request): 36 # if request.COOKIES.get(‘name‘): 37 # return HttpResponse(‘我是index页面,只有登录了才能看‘) 38 return HttpResponse(‘index‘) 39 40 @login_auth 41 def home(request): 42 return HttpResponse(‘home‘) 43 44 @login_auth 45 def order(request): 46 return HttpResponse(‘home‘) 47 48 49 def logout(request): 50 res = redirect(‘/login‘) 51 res.delete_cookie(‘name‘) 52 return res 53 54 55 def set_session(request): 56 #设置键值对 57 request.session[‘gender‘] = ‘hasdhsjka‘ 58 #上面这句话干了这三件事 59 #1.内部自动生成一个随机字符串,一个浏览器对应一个 60 #2.将随机字符串与数据字典存入django session表中 61 #3.将随机字符串设置到浏览器的cookie中 62 return HttpResponse(‘ok‘) 63 64 def get_session(request): 65 print(request.session.get(‘gender‘)) 66 return HttpResponse(‘ok‘)
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 <form action="" method="post"> 9 <p>username:<input type="text" name="username"></p> 10 <p>password:<input type="text" name="password"></p> 11 <input type="submit"> 12 </form> 13 </body> 14 </html>
原文:https://www.cnblogs.com/huangxuanya/p/11029135.html