django中间件补充、django操作cookie与session

django中间件补充、django操作cookie与session

基于django中间件实现功能的插拔式设计

在使用自定义中间件时可以注意到,通过注册来启动或关闭一个功能十分便捷,这种方式被称为功能的插拔式设计。
使用方式:
    1.将各个功能制作成配置文件的字符串形式;
    2.想拥有该功能就编写对应的字符串;
    3.不想有该功能则注释对应的字符串即可。

# 使用importlib模块模仿django中间件调用功能的方式
    importlib可以帮忙用字符串导入模块,拿到模块名的字符串,importlib可以搜索模块并执行导入操作:
    import importlib   # 引入模块
    s1 = 'bbb.b'  # aaa.bbb.ccc.b
    res = importlib.import_module(s1)  # from aaa.bbb.ccc import b
    print(res)  # <module 'bbb.b' from 'D:\\pythonProject03\\djangomiddle\\bbb\\b.py'>
    s2 = 'aaa'
    res=importlib.import_module(s2) 
    # 相当于import aaa 并将模块设置为res
'''注意字符串的结尾最小单位只能是py文件 不能是py文件里面的变量名'''

# 功能模拟——编写一个消息通知功能(微信、QQ、邮箱)
	实现方式1:基于函数封装的版本
    def qq(content):
    	print('来自qq的消息:%s', % content)
    def wechat(content):
        print('来自微信的消息:%s', % content)
    def email(content):
        print('来自邮箱的消息:%s', % content)

    def send_all(content):
        # qq(sontent)  不想发哪个消息就注释哪个函数
        wechat(content)
        email(content)

    if __name__ == 'main':
        send_all('元旦三天假 你想怎么过?')

    使用函数封装三个发送消息的应用,用启动函数运行。当不想执行某个应用的消息通知功能时,就将这个应用的此功能在启动函数中对应的调用代码注释掉即可。
    缺点:很一般,毫无新意
    
    实现方式2:基于django中间件的功能设计
    1.importlib
        通过字符串导入模块
    2.从右开始切割字符串
        rsplit
    3.反射
        将模块名看成是对象通过反射回去该模块中字符串对应的名字
    4.面向对象的多态性
    优点: 眼前一亮,回味无穷
        
# 模块对象的反射
	python中一切皆对象,模块也是一种对象。模块的名称空间中的名字就是模块对象的属性。所以对于一个模块,我们可以通过反射的方式取到其中的类、函数、变量等名字。

# 仿django配置文件注册
# MyMiddleWare文件夹midware01.py中
class MidWare01(MiddlewareMixin):
    def process_request(self, request):
        print('from MidWare01 request')
        
# MyMiddleWare文件夹midware02.py中
class MidWare02(MiddlewareMixin):
    def process_request(self, request):
        print('from MidWare01 request')
        
# 注册配置
MIDWARE_LIST = [
    'MyMiddleWare.midware01.MidWare01',
    'MyMiddleWare.midware02.MidWare02',
]

# 按照注册顺序,执行每个类中的process_request方法
import importlib
def all_exec(request):
    for full_path in MIDWARE_LIST:
        # 将字符串切割为模块路径和类名
	    path, cls_name = full_path.rsplit('.', max_split=1) 
        # 通过模块路径字符串拿到模块名
        module_name = importlib.import_module(path)  
        # 通过模块名反射拿到类名
        cls = getattr(module_name, cls_name)  
        # 通过类产生对象
        obj = cls()  
        # 通过对象使用方法
        obj.process_request(request)  
        # 多态的思想,因为大家的这个功能一致,所以方法名也该一致

cookie与session简介

HTTP协议四大特性:
    1.基于请求响应
    2.基于TCP、IP作用于应用层之上的协议
    3.无状态,不保存客户端的状态
    4.无连接

需求变化:
    最开始的网站都不需要用户注册,所有人来访问获取到的数据都是一样的;
    随着互联网的发展,很多网站需要指定当前用户的状态,因此需要用到cookie和session

cookie
	保存在客户端,存储与用户状态相关的信息
session
	保存在服务端,存储与用户状态相关的信息
# session的工作需要依赖于cookie

补充:
    浏览器有资格拒绝保存服务端发送过来的cookie数据(需要在设置里设置,但都拒绝的话会出现不能登陆的情况)
    可以在浏览器中右键检查查看cookies信息,如果主动删除这些cookies信息就需要重新登陆。但若短时间频繁操作,可能被某些网页检测到导致被封ip

django操作cookie

from django.shortcuts import render,HttpResponse,redirect
return render()
return HttpResponse()
return redirect()

要想操作cookie就不能直接返回HttpResponse对象 必须先用变量接收
obj1 = render()
return obj1
obj2 = HttpResponse()
return obj2
obj3 = redirect()
return obj3

# 用户登录功能
用户未登录想访问某个网站,输入用户名密码之后就应该调回该网站
def login_func(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        if username == 'jason' and password == '123':
            target_path = request.GET.get('next')
            if target_path:
                obj = redirect(target_path)
            else:
                obj = redirect('/home/')
            obj.set_cookie('name', username)
            return obj
    return render(request, 'loginPage.html')

def login_auth(func_name):
    def inner(request, *args, **kwargs):
        print(request.path)  
        # 只获取用户输入的路由信息
        print(request.path_info)  
        # 只获取用户输入的路由信息
        
'''request.path和request.path_info都能拿到请求页面的路由,这样我们就能记录下是哪个页面想服务端发送了请求'''
        target_path = request.path_info
        print(request.get_full_path())  
        # 获取用户输入的路由信息+问号后面携带的数据
        if request.COOKIES.get('name'):
            res = func_name(request, *args, **kwargs)
            return res
        
'''将路由拼接在/login/?的后面,在登录界面可以将路由拿到并进行跳转'''
        return redirect('/login/?next=%s' % target_path)

    return inner
# 退出登录本质就是将客户端的标识用户身份的cookie删除掉

django操作session

session是保存在服务端上面的数据就应该有个地方能够存储,我们只需要执行数据库迁移命令即可,django会自动创建很多需要的表。
django默认的session失效时间是14天。

# 设置session
语法结构:request.session['key']=value
def session_func(request):
    request.session['session的键'] = '今天疯狂星期四'
    return HttpResponse('session_func')
	
设置session时会执行下列操作:
	1.当执行request.session['key']=value之后,首先生成一个随机字符串,就是session_key;
	2.对value做加密处理,django会在django_session表中存储session_key以及session_data的对应关系。session_data对应的就是我们添加的值'今天疯狂星期四';
	3.将随机字符串session_key发送一份给cookie。
    此后登陆服务端session会校验用户是否有该字符串,如果有的话在一定时间内就可以不用登录。
    
# 获取session
语法结构:request.session.get('key')
def session_get(request):
    print(request.session.get('session的键'))
    return HttpResponse('session_get')  # 今天疯狂星期四

获取session时会执行下列操作:
	1.自动获取客户端携带的加密字符串
	2.自动去django_session表中根据随机字符串获取加密的数据
    	(比对是否有对应记录)
	3.如果有自动获取加密的数据并解密到request.session.get()中
    
# 补充说明
	1.可以设置过期时间		
 	2.存储session数据的位置也可以修改

# 将所有Session失效日期小于当前日期的数据删除
	request.session.clear_expired()

# 检查会话session的key在数据库中是否存在
	request.session.exists("session_key")

# 删除当前会话的所有Session数据
	request.session.delete()

# 删除当前的会话数据并删除会话的Cookie。
	request.session.flush() 

# 设置会话Session和Cookie的超时时间
	request.session.set_expiry(value)
    * 如果value是个整数,session会在些秒数后失效;
    * 如果value是个datatime或timedelta,session就会在这个时间后失效;
    * 如果value是0,用户关闭浏览器session就会失效;
    * 如果value是None,session会依赖全局session失效策略。
posted @ 2023-01-04 17:28  知了了了了  阅读(46)  评论(0编辑  收藏  举报