目录
Cookie与Session原理
为什么会有这些技术?
原因:HTTP协议是无状态的
目的:是为了保护客户端的用户状态
什么Cookie
保存在客户端浏览器上的键值对
cookie虽然是保存在客户端浏览器上的键值对,但是它是由服务端设置的
浏览器有权禁止cookie的写入
Cookie的原理
由服务端产生内容,浏览器接收请求后保存在本地,当浏览器再次访问时,浏览器会自动带上cookie,这样服务器就能通过cookie的内容来判断这个是谁
查看Cookie步骤
使用谷歌浏览器,打开开发者工具(F12)检查,Network->Cookie 就能查看到一个个的键值对
如何设置Cookie
obj.set_cookie('k1','v1')告诉浏览器设置
如何获取Cookie
request.COOKIES.get('k1')获取浏览器携带过来的cookie值
如何设置Cookie的超时时间
obj.set_cookie('k1','v1',max_age=3)
obj.set_cookie('k1','v1',expires=3)
两个参数都是设置超时时间,并且都是以秒为单位
区别:如果你要给IE浏览器设置cookie的超时时间,只能用expires
如何删除Cookie
rep.delete_cookie("user") # 删除用户浏览器上之前设置的usercookie值
什么是session
保存在服务端上面的键值对
session的工作机制是需要依赖于cookie的
设置session
request.session['k1'] = 'v1'
第一次设置的时候会报错,因为你没有执行数据库迁移命令,生成django需要用到的一些默认表(django_session)
request.session['k1'] = 'v1'
上面这一句话到底发生了哪些事儿
1.djang内部自动帮你调用算法生成一个随机的字符串
2.在django_session添加数据(数据也是加密处理)
随机字符串 加密之后的数据 失效时间
ashdjsad jsadsada
3.将产生的随机字符串返回给客户端浏览器 让浏览器保存
sessionid:随机字符串
获取session
request.session.get('k1')
1.django内部会自动去请求头里面获取cookie
2.拿着sessionid所对应的随机字符串去django_sessoion表中一一比对
3.如果比对上了 会将随机字符串对应的数据获取出来
#自动放入request.session中供程序员调用
如果没有就是一个空字典
删除session
request.session.delete()
客户端和服务端全部删除 只会根据浏览器的不同删对应的数据
如何设置失效时间
# 设置会话Session和Cookie的超时时间
request.session.set_expiry(value)
* 如果value是个整数,session会在该秒数后失效。
* 如果value是个datatime或timedelta,session就会在这个时间后失效。
* 如果value是0,用户关闭浏览器session就会失效。
* 如果value是None,session会依赖全局session失效策略。
django session在创建数据的时候 是针对浏览器的
能够作为数据库的有哪些
数据库软件
关系型
非关系型
文件
内存
token
加密字符串
加密算法 xxx
username 》(xxx)》 随机字符串
username + 随机字符串
django中间件
django默认有七个中间件
只要你想要做一些网站的全局性功能 你都应该考虑使用django的中间件
1.全局的用户登录校验
2.全局的用户访问频率校验
3.全局的用户权限校验() 20行代码 100+ RBAC
django的中间件是所有框架里面做的最完善的
对象 字符串 》》》 反射
全局 》》》 中间件
需要掌握
并且支持用户自定义中间件 然后暴露给用户五个可以自定义的方法
需要掌握
process_request(******)
1.请求来的时候会按照settings配置文件中从上往下的顺序
依次执行每一个中间件内部定义的process_request方法
如果中间件内部没有该方法 直接跳过执行下一个中间件
2.该方法一旦返回了HttpResponse对象,那么请求会立刻停止往后走 原路立即返回
process_response
1.响应走的时候会按照settings配置文件中从下往上的顺序
依次执行每一个中间件内部定义的process_response方法
2.该方法必须有两个形参 并且必须返回response形参 不返回直接报错
3.该方法返回什么(HttpResponsed对象) 前端就能获得什么
# 当process_request方法直接返回HttpResponse对象之后
会 直接从当前中间件里面的process_respone往回走
# 没有执行的中间件都不会再执行
需要了解
process_view(self,request,view_name,*args,**kwargs)
1.路由匹配成功之后在执行视图函数之前触发
2.如果该方法返回了HttpResponse对象 那么会从下往上一次经过每一个中间件里面的process_response方法
process_template_response
1.当你返回的对象中含有render属性指向的是一个render方法的时候才会触发 从下往上的顺序
def mdzz(request):
print('我是视图函数mdzz')
def render():
return HttpResponse('你好呀 我是奇葩')
obj = HttpResponse('我很好 好的像个傻逼一样')
obj.render = render
return obj
process_exception
1.当视图函数中出现错误 会自动触发 顺序是从下往上
上面这五个方法 会在特定的阶段自动触发
# 如果形参中含有response 那么必须要返回
django默认的session失效时间
失效时间是14天(2周)
今日考题
-
请描述一下多对多可以有几种创建方式,具体说说每种方式,全自动和半自动在参数有何不同
全自动 ManyToManyField
纯手动
半自动 through自己指定第三张关系表
`through_fields自己指定第三张关系表中 到底哪两个字段维护者表与表之间的多对多关系`
-
forms组件是干什么用的,它的主要功能有哪些功能,你能否具体说说每个功能下都有哪些经常用到的方法及注意事项(越详细越好)
1.手动书写html代码获取用户输入 》》》 渲染标签 2.将数据转递给后端做数据校验 》》》 校验数据 3.如果数据有错误 你还展示了错误信息 》》》 展示信息
-
forms组件钩子函数是干什么用的,如何编写,请举例说明
对数据进行校验
- 局部钩子
我们在Fom类中定义 clean_字段名() 方法,就能够实现对特定字段进行校验。
class LoginForm(forms.Form): username = forms.CharField( min_length=8, label="用户名", initial="张三", error_messages={ "required": "不能为空", "invalid": "格式错误", "min_length": "用户名最短8位" }, widget=forms.widgets.TextInput(attrs={"class": "form-control"}) ) ... # 定义局部钩子,用来校验username字段 def clean_username(self): value = self.cleaned_data.get("username") if "666" in value: raise ValidationError("光喊666是不行的") else: return value
- 全局钩子
我们在Fom类中定义 clean() 方法,就能够实现对字段进行全局校验。
class LoginForm(forms.Form): ... password = forms.CharField( min_length=6, label="密码", widget=forms.widgets.PasswordInput(attrs={'class': 'form-control'}, render_value=True) ) re_password = forms.CharField( min_length=6, label="确认密码", widget=forms.widgets.PasswordInput(attrs={'class': 'form-control'}, render_value=True) ) ... # 定义全局的钩子,用来校验密码和确认密码字段是否相同 def clean(self): password_value = self.cleaned_data.get('password') re_password_value = self.cleaned_data.get('re_password') if password_value == re_password_value: return self.cleaned_data else: self.add_error('re_password', '两次密码不一致') raise ValidationError('两次密码不一致')
-
面相对象中的__init__和__new__的区别是什么,利用__new__可以实现什么
__new__的调用先于 __init__ 方法; __new__ 方法负责创建一个实例对象,__init__ 方法负责将该实例对象进行初始化。 __new__方法正是创建这个类实例的方法,返回的对象正是 __init__ 的 self 参数; __init__ 用于实例化对象,__new__用于继承,是类别级的方法;
new 的应用场景
__new__方法主要是当你继承一些不可变的class时(比如int, str, tuple), 提供给你一个自定义这些类的实例化过程的途径
```
class PositiveInt(int):
def __init__(self, value):
return super(PositiveInt, self).__init__(self, abs(value))
class PositiveInt(int):
def __new__(cls, value):
return super(PositiveInt, cls).__new__(cls, abs(value))