Django——Session源码分析

首先我们导入django.contrib.sessions.middleware这个中间件,查看里面的Session源码
from django.contrib.sessions.middleware import SessionMiddleware
我们可以看到一个类,可以把他分为3部分:
class SessionMiddleware(MiddlewareMixin):
    def __init__(self, get_response=None):
        ...

    def process_request(self, request):
        ...

    def process_response(self, request, response):
        ...
接下来我们会逐个进行分析:1.__init__ 初始化代码如下:
def __init__(self, get_response=None):
    self.get_response = get_response  #(1)
    engine = import_module(settings.SESSION_ENGINE)  #(2)
    self.SessionStore = engine.SessionStore  #(3)
# 我们知道__init__()是一个类的魔法方法,实例化一个对象的时候就会执行里面的代码(1)self.get_response = get_response    # 这是一个赋值操作

(2)engine = import_module(settings.SESSION_ENGINE)    # import是导入一个模块名,而import_module可以将字符串所代表的模块名导入,    # 我们可以断定settings.SESSION_ENGINE的最终结果就是一个字符串

关于settings一共有三个,在我们新建的项目文件夹中就有一个,我们去找SESSION_ENGINE这个变量,发现没有    往上面看,发现有这个from django.conf import settings,我们在这个django.conf.settings里面继续找SESSION_ENGINE,也没有找到    在django.conf.settings这个配置文件中,我们发现这个from django.conf import global_settings,    在这个配置文件中有这么一行SESSION_ENGINE = ‘django.contrib.sessions.backends.db‘,这句话是干啥的,先不管

(3)self.SessionStore = engine.SessionStore    要弄清这句话的意思,我们就必须弄明白engine是个什么东西,那它到底是个什么东西了?    我们把‘django.contrib.sessions.backends.db‘这句话展开,发现里面是这样的
    class SessionStore(SessionBase):
        ...
    它就是一个类,现在貌似我们就有点头绪了。engine就是导入一个db文件,    而self.SessionStore = engine.SessionStore就只是单纯的实例化一个类名    关于SessionStore,我们可以先说一句,这个类session最重要的一个类,所有的操作基本跟它有关

2.process_request# 代码如下:
def process_request(self, request):
    session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME)
    request.session = self.SessionStore(session_key)
(1)session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME)    这句话是从COOKIES里面来获取值,同样我们去global_settings这个文件中找出SESSION_COOKIE_NAME,    SESSION_COOKIE_NAME = ‘sessionid‘,现在我们大概明白,这句话就去COOKIES取叫做sessionid这个键的值

(2)request.session = self.SessionStore(session_key)    上面已经取出session_key值,可以不存在,然后我们看SessionStore这个类到底是个什么玩意    代码如下:
    class SessionStore(SessionBase):
        def __init__(self, session_key=None):
            super(SessionStore, self).__init__(session_key)
        #下面如果函数,不管    上面代码的意思就是说SessionStore继承SessionBase,那么我们就去这个类里面看看,里面有这些代码需要我们留意
    class SessionBase(object):

        def __init__(self, session_key=None):
            self._session_key = session_key
            self.accessed = False
            self.modified = False
            self.serializer = import_string(settings.SESSION_SERIALIZER)

        def __contains__(self, key):
            return key in self._session

        def __getitem__(self, key):
            return self._session[key]

        def __setitem__(self, key, value):
            self._session[key] = value  #这个是赋值操作
            self.modified = True

        def __delitem__(self, key):
            del self._session[key]

        #下面定义了许多函数也不管,应为此时并没有调用,上面都是一些魔法函数,
        # 分别定义了取值的时候干啥、赋值的时候干啥等,此时我们必须弄清_session这个是啥?
        往下看,又有如下代码:
        def _get_session(self, no_load=False):

            self.accessed = True
            try:
                return self._session_cache  #如果没有异常,就返回缓存
            except AttributeError:
                if self.session_key is None or no_load:   #如果没有session_key或没有加载
                    self._session_cache = {}  #就是一个空字典
                else:
                    self._session_cache = self.load()
            return self._session_cache  #总之最后要返回这个值

        _session = property(_get_session)
    我们再回来看request.session = self.SessionStore(session_key),他就是返回一个session对象    有没有值还是另说,因为你不知道self._session_cache这个是否有值

(3)views中的视图操作,我们把自己写的拿过来,有这句话,request.session["user"] = user    结合上面的_get_session函数,此时self._session_cache有值了,但是如我们刚才所说的,并没有一定写进数据库了

(4)process_response代码如下:
def process_response(self, request, response):
    """
    If request.session was modified, or if the configuration is to save the
    session every time, save the changes and set a session cookie or delete
    the session cookie if the session has been emptied.
    如果request.session被修改,或者配置每次都保存,会保存修改和者设置cookie。或删除ifsession已经被清空。
    """
    #如果我们有赋值操作
    try:
        accessed = request.session.accessed
        modified = request.session.modified
        empty = request.session.is_empty()
        """
            def is_empty(self):
                "Returns True when there is no session_key and the session is empty"
                try:
                    return not bool(self._session_key) and not self._session_cache
                    #有_session_key和_session_cache都会返回False
                except AttributeError:
                    return True
        """
    except AttributeError:
        pass
    else:
        # First check if we need to delete this cookie.  #首先检查我们是否需要删除这个cookie
        # The session should be deleted only if the session is entirely empty  #只有会话完全空时才应删除会话。
        if settings.SESSION_COOKIE_NAME in request.COOKIES and empty:
            #如果这个sessionid在cookie中,或者为空
            #上面说过有_session_key和_session_cache都会返回False,有就不删
            response.delete_cookie(  #删除cookie
                settings.SESSION_COOKIE_NAME,
                path=settings.SESSION_COOKIE_PATH,
                domain=settings.SESSION_COOKIE_DOMAIN,
            )
        else:
            if accessed:
                patch_vary_headers(response, (‘Cookie‘,))
            if (modified or settings.SESSION_SAVE_EVERY_REQUEST) and not empty:
                if request.session.get_expire_at_browser_close():  #这个是设置过期时间的
                    max_age = None
                    expires = None
                else:
                    max_age = request.session.get_expiry_age()
                    expires_time = time.time() + max_age
                    expires = cookie_date(expires_time)
                # Save the session data and refresh the client cookie.  #保存会话数据并刷新客户端cookie。
                # Skip session save for 500 responses, refs #3881.
                if response.status_code != 500:
                    try:
                        request.session.save()  #没有错误才会保存到数据库
                    except UpdateError:
                        raise SuspiciousOperation(
                            "The request‘s session was deleted before the "
                            "request completed. The user may have logged "
                            "out in a concurrent request, for example."
                        )
                    response.set_cookie(   #最后设置客户端cookie
                        settings.SESSION_COOKIE_NAME,  #设置sessionid
                        request.session.session_key, max_age=max_age,
                        expires=expires, domain=settings.SESSION_COOKIE_DOMAIN,
                        path=settings.SESSION_COOKIE_PATH,
                        secure=settings.SESSION_COOKIE_SECURE or None,
                        httponly=settings.SESSION_COOKIE_HTTPONLY or None,
                    )
    return response

上面就是一个session的生成的整个过程。



原文地址:https://www.cnblogs.com/yangmingxianshen/p/8521905.html

时间: 2024-11-02 11:35:35

Django——Session源码分析的相关文章

Flask框架 —— session源码分析

目录 session源码分析 1.请求来了,执行__call__方法 2.__call__方法 3.调用__call__方法 3.1.ctx = self.request_context(environ) --- 得到空的session 3.2.ctx.push() --- 调用open_session方法 3.3.self.full_dispatch_request() --- 路由分发,执行函数,写入session session源码分析 1.请求来了,执行__call__方法 # 请求来了

Flask中session源码执行过程

1.面向对象补充知识metaclass 创建类就可以有两种方式: a.普通方式 1 class Foo(object): 2 3 def func(self): 4 print 'hello wupeiqi' b.特殊方式(type类的构造函数) 1 def func(self): 2 print 'hello wupeiqi' 3 4 Foo = type('Foo',(object,), {'func': func}) 5 #type第一个参数:类名 6 #type第二个参数:当前类的基类

python第七十二天,admin源码分析

django settings 源码分析 导入settingso模块,进入源码,会发现settings是一个 单例 LazySettings类实例化产生的一个对象,LazySettings实例化后就会走它内部的_setup函数 importlib模块的作用 : 以字符串的形式导入模块,拿到能够访问该模块名称 空间的名字module = imporlib.import_module('字符串') settings配置用户自定义的原理:项目启动后,会使用os.environ.settdefault(

django的RBAC认证z;自定义auth_user表;认证组件权限组件源码分析;认证组件;权限组件

一 RBAC 1.RBAC:全称(Role-Based Access Control):指的是基于用户权限访问控制的认证. 2.Django框架采用的是RBAC认证规则,RBAC认证规则通常会分为:三表规则,五表规则:Django采用的是六表规则. # 三表:用户表.角色表.权限表# 五表:用户表.角色表.权限表.用户角色关系表.角色权限关系表# 六表:用户表.角色表.权限表.用户角色关系表.角色权限关系表.用户权限关系表 3.在Django中六表之间是都是多对多的关系,可通过下面字段跨表访问

Tomcat源码分析——Session管理分析(上)

前言 对于广大java开发者而已,对于J2EE规范中的Session应该并不陌生,我们可以使用Session管理用户的会话信息,最常见的就是拿Session用来存放用户登录.身份.权限及状态等信息.对于使用Tomcat作为Web容器的大部分开发人员而言,Tomcat是如何实现Session标记用户和管理Session信息的呢? 概要 Session Tomcat内部定义了Session和HttpSession这两个会话相关的接口,其类继承体系如图1所示. 图1 Session类继承体系 图1中额

Django——基于类的视图源码分析 二

源码分析 抽象类和常用视图(base.py) 这个文件包含视图的顶级抽象类(View),基于模板的工具类(TemplateResponseMixin),模板视图(TemplateView)和重定向视图(RedirectView). View及View的执行顺序 View是所有基于类的视图的基类.仅实现了一些基本的方法和必要的检查工作.其中最重要的是dispatch方法.再次方法中,根据HTTP请求 中的method参数,调用相应的同名处理函数.这里留下了一个口子,后续的类需要根据自己的情况来填补

Tomcat7.0源码分析——Session管理分析(上)

前言 对于广大java开发者而已,对于J2EE规范中的Session应该并不陌生,我们可以使用Session管理用户的会话信息,最常见的就是拿Session用来存放用户登录.身份.权限及状态等信息.对于使用Tomcat作为Web容器的大部分开发人员而言,Tomcat是如何实现Session标记用户和管理Session信息的呢? 概述 Session Tomcat内部定义了Session和HttpSession这两个会话相关的接口,其类继承体系如图1所示. 图1 Session类继承体系图1中额外

Django搭建及源码分析(三)---+uWSGI+nginx

每个框架或者应用都是为了解决某些问题才出现旦生的,没有一个事物是可以解决所有问题的.如果觉得某个框架或者应用使用很不方便,那么很有可能就是你没有将其使用到正确的地方,没有按开发者的设计初衷来使用它,当你将一个框架的优势使用到极致时一定是非常舒服和顺手的一件事.但同时也有可能衍生另一个问题,这个框架只解决了你的问题一,没有解决问题二.三等等,因此,就出现了多个框架/应用相结合的情况.比如Django + uWSGI + nginx. 本人初学python,找了一些实例进行了一些操作,以下纯属目前的

Django之admin的使用及源码分析

一.admin组件使用 Django本身提供了基于 web 的管理工具.其管理工具是django.contrib的一部分,可在settings.py中的 INSTALLED_APPS 看到: INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'dj