django之forms组件,cookie&session

forms组件

先自己实现注册功能,并且对用户输入的信息加限制条件
如果用户输入的信息不符合条件,前端展示报错信息
 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())
Views.py
 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

注意: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).']
}
"""
几个图例看看更清楚哦?

?????

???

???

???

???

forms渲染标签

渲染标签
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>
reg.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>

 

 

 

forms组件局部钩子,全局钩子

#钩子函数
#局部钩子
#如想给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())
Views.py
 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
 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>
reg1.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>
reg2.html

forms组件扩展字段

 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     )
Views.py

cookie

本质:保存在浏览器上的键值对 
用途:标识当前用户信息
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

本质:保存在服务器上的键值对
用途:记录当前用户信息
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')
Views.py
 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>
login.html

 总结

   forms组件
三大功能:
1.渲染前端html代码
2.校验数据
3.返回校验信息并且展示到前端
校验数据:
from django import forms


class RegForm(forms.Form):
name = forms.CharField(max_length=8,
min_length=3,
error_message={
'max_length':'用户名最长8位',
'min_length':'用户名最短3位',
'required':'改字段必填'
})
password = forms.CharField(max_length=8,
min_length=3,
label='密码',
error_message={
'max_length':'密码最长8位',
'min_length':'密码最短3位',
'required':'改字段必填'
},widget=forms.PasswordInput(attrs={'class':'form-control'}))
confirm_password = forms.CharField(max_length=8,
min_length=3,
label='确认密码',
error_message={
'max_length':'确认密码最长8位',
'min_length':'确认密码最短3位',
'required':'改字段必填'
},widget=forms.PasswordInput(attrs={'class':'form-control'}))
email = forms.EmailField(error_message={
'required':'改字段必填',
'invalid':'邮箱格式不正确'
})

# 局部钩子
def clean_name(self):
name = self.cleaned_data.get('name')
if '666' in name:
self.add_error('name','光喊666是不行的!')
else:
return name

# 全局钩子
def clean(self):
password = self.cleaned_data.get('password')
confirm_password = self.cleaned_data.get('confirm_password')
if not password == confirm_password:
self.add_error('confirm_password','两次不一致')
else:
return self.cleaned_data



form_obj = RegForm({'name':'jason','password':'123','email':'123@qq.com'})
if form_obj.is_valid():
pass
form_obj.cleaned_data
else:
form_obj.errors
渲染前端html代码常见方式
1.{{ form_obj.as_p }}
2.{{ form_obj.name.label }}{{ form_obj.name }}
3.
{%for foo in form_obj %}
<p>
{{ foo.label }}
{{foo}}
<span>{{ foo.errors.0 }}</span>
</p>
{% endfor %}
校验数据
钩子函数
局部钩子
# 见上文
全局钩子
# 见上文

forms组件扩展



Cookie与Session
两者的由来:归功于http协议无状态特性
Cookie:存储在浏览器上的k,v键值对
Session:存储在服务器上的k,v键值对


两者的设置,获取,删除
Cookie的操作需要依赖于HttpResponse对象
res = render(...)
res.set_cookie('','',max_age=12)
request.COOKIES.get('')

Session的操作
request.session['name'] = 'egon'
"""
1.内部自动生成一个随机字符串
2.服务端默认的session表里面存入数据
表头 随机字符串 value time
fafafjdsfsaf {k:v,...} django默认的session超时时间为14天
3.将随机字符串写到浏览器的cookie中
sessionid:随机字符串
"""

 

转载于:https://www.cnblogs.com/huangxuanya/p/11029135.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值