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周)

今日考题

  1. 请描述一下多对多可以有几种创建方式,具体说说每种方式,全自动和半自动在参数有何不同

    全自动 ManyToManyField

    纯手动

    半自动 through自己指定第三张关系表

                      `through_fields自己指定第三张关系表中 到底哪两个字段维护者表与表之间的多对多关系`
    
  2. forms组件是干什么用的,它的主要功能有哪些功能,你能否具体说说每个功能下都有哪些经常用到的方法及注意事项(越详细越好)

     1.手动书写html代码获取用户输入             》》》    渲染标签
     2.将数据转递给后端做数据校验               》》》    校验数据
     3.如果数据有错误 你还展示了错误信息         》》》    展示信息
    
  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('两次密码不一致')
    
  4. 面相对象中的__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))