Django session 详解

el/2024/7/17 21:23:01

Django中的session是一个高级工具,它可以让用户存储个人信息以便在下次访问网站中使用这些信息。session的基础还是cookie,但是它提供了一些更加高级的功能。请看下面的一个例子:

使用session:

这个例子中实现了一个简单的计数功能:

def test_count_session(request):
    if 'count' in request.session:
        request.session['count'] += 1

        return HttpResponse('new count=%s'   % request.session['count'])
    else:
        request.session['count'] = 1
        return HttpResponse('No count in session. Setting to 1')

比较session和cookie的使用我们可以发现他们有一下几点不同:

  • session管理更加统一和方便:每个session中的属性值可以使用查询以及修改操作。
  • 虽然我们在例子中只是使用了一个整数的属性,但实际上session中还可以包含很多类型的属性,比如字典属性,并且它可以很方便地用Python中的内建方法访问它们。

虽然我们在session中设置了一个计数器count,但是如果我们抓取当前的cookie时会发现,竟然没有count这个属性!而只是设置了一个看起来似乎是唯一标识的sesionid,这当然是处于安全方面的考虑。假定用户不停地访问一个页面,比如访问了10次,那我们是不是就要对他的计数器+10次呢?显然这样做不符合实际情况,有了这个sessionid,我们就可以判断是否是同一个用户访问一个页面了。

Set-Cookie:sessionid=a92d67e44a9b92d7dafca67e507985c0;
expires=Thu, 07-Jul-2011 04:16:28 GMT;
Max-Age=1209600;
Path=/

深入了解sessionid

默认情况下,Django会将session保存在django_session这个表中:

CREATE TABLE "django_session" (
    "session_key" varchar(40) NOT NULL PRIMARY KEY,
    "session_data" text NOT NULL,
    "expire_date" datetime NOT NULL
);

其中的session_key就相当于cookie中保存的sessionid,而session_data就包含了当前session中的属性。

如果想详细看看我们上面创建的session的信息,可以像下面这样:

from django.contrib.sessions.models import Session
#...
sess = Session.objects.get(pk='a92d67e44a9b92d7dafca67e507985c0')
print(sess.session_data)
print(sess.get_decoded()

 它或许会输出类似下面的信息:

ZmEyNDVhNTBhMTk2ZmRjNzVlYzQ4NTFjZDk2Y2UwODc3YmVjNWV

jZjqAAn1xAVUFY291bnRxAksGcy4=

{'count': 11}

Django会保存request.session的相关信息到数据库,然后用户可以通过cookie中的sessionid对它进行各种操作。当然这些操作我们可以通过Django自带的session模块轻松操作,从而简化了程序员的工作。下面我们来详细了解一下Django中的session。

 

session中间件:

首先看看Django中的django.http.HttpRequest,了解一下它是如何取得session并对其属性进行操作的。

the Django Book中对它有详细的介绍,我们这里就简单的说一下原理吧 ! 

视图方法接受一个httprequest后,对它进行一系列的操作,然后返回一个httpresponse。而中间件增加一些额外的操作:

Django的中间件框架就是一些所谓的hook类,它设置在Django项目中的settings中的MIDDLEWARE_CLASSES内。当然您也可以添加自己的MIDDLEWARE_CLASSES。

默认情况下,django.contrib.sessions.middleware.SessionMiddleware 是自动添加的。查看它的源代码,我们可以发现它实际上就是实现了2个hooks:process_requestprocess_response

process_request提取当前cookie中的session KEY(也就是sessionid),其中SESSION_COOKIE_NAME就是我们说的sessionid。而request.session则包含了"session store"对象。

process_response负责保存"session store"对象并将它返回给客户端。

 

session的存储:

Django中可以通过设置SESSION_ENGINE属性来指定后台引擎来处理session。默认是django.contrib.sessions.backends.db。

在Django安装目录中的sessions/backends下可以找到很多其他的引擎,这里就不再赘述。

不管是哪一种引擎,它都实现了一个StorageSession类,其中包含了对session的各种操作方法。

为了理解它的工作原理,假定用户想访问request.session,来看看它的工作流程:

  1. Session中间件的process_request实例化一个request.session,并将db.SessionStore附带session_key保存到构造函数(姑且这么叫吧,实在想不到好听的名字)。
  2. SessionStore的构造函数会保存session key以便用户访问。
  3. process_request的工作就算完成了,接着session中间件会将request传给view方法。
  4. SessionBase是一个类字典实例,我们可以通过Python内建的字典方法对它进行操作,例如__getitem__。它还有一个很有用的方法:_get_session(它用到了load方法,load方法是由db.SessionStore来执行的,而不是SessionBase,期间还有一些对数据的编码工作)

下面来看一个简单的例子:

def encode(self, session_dict):
    "Returns the given session dictionary pickled and encoded as a string."
    pickled = pickle.dumps(session_dict, pickle.HIGHEST_PROTOCOL)
    hash = self._hash(pickled)
    return base64.encodestring(hash + ":" + pickled)

结论:

Django基于最简单的HTTP request和HTTP response而实现session的使用。希望上面的一些东西能给您带来一些灵感,如果需要详细了解session,读者可以当django官网的session文档中去找。


http://www.ngui.cc/el/5557147.html

相关文章

python的os模块fork、wait、system、exec、popen、exit函数讲解

虽然进程可在单独的内存空间中执行,但除非这些Python进程在单独的处理器上执行,否则,实际并不是“同时”运行的。是由操作系统把处理器的时间片分配给一个进程,用完 时间片 后就需退出处理器等待另一个时间片的到来。 另一种方式…

Python:OS 模块 -- 进程管理

原文链接:http://www.cnblogs.com/now-fighting/p/3534847.html 建议查看原作者原文。 这里我们介绍os模块中的进程管理相关的操作。 os模块提供给了我们访问操作系统功能的接口,我们可以通过os模块提供给我们的进程管理接口,编写多进程程…

Ubuntu下怎么安装openjdk

方法/步骤 1 ubuntu使用的是openjdk,我门要首先找到适合的jdk版本。 2 在终端输入命令:apt-cache search openjdk 3 从搜索的列表里找到我们需要安装的jdk版本 4 执行安装命令:sudo apt-get install openjdk-7-jdk 5 注意openjdk-7-jdk就是我…

linux shell 解读 “永久环境变量” “临时环境变量”和普通变量

一. 永久环境变量(实际上属于文件, 而不属于shell, 每打开一个shell, 都会加载/导入到shell中, 形成当前shell的临时环境变量) 先说说"永久环境变量", 其实, 我也知道, 没有什么东西是…

SQL左连接、右连接、笛卡尔积的表现形式

表A记录如下: aID aNum 1 a20050111 2 a20050112 3 a20050113 4 a20050114 5 a20050115 表B记录如下: bID bName 1 2006032401 2 2006032402 3 2006032…

Shell脚本中执行sql语句,操作mysql数据库

对于自动化运维,诸如备份恢复之类的,DBA经常需要将SQL语句封装到shell脚本。本文描述了在Linux环境下mysql数据库中,shell脚本下调用sql语句的几种方法,供大家参考。对于脚本输出的结果美化,需要进一步完善和调整。以下…

django get_object_or_404

django get_object_or_404 是django shortcuts模块里面一个比较简便的方法,特别是用django get来操作数据库的时候,可以帮 我们少写一些代码,加快开发速度。 get_object_or_404的介绍: 我们原来调用django 的get方法,…

sql语句每个关键字的执行顺序

SQL 不同于与其他编程语言的最明显特征是处理代码的顺序。在大数编程语言中,代码按编码顺序被处理,但是在SQL语言中,第一个被处理的子句是FROM子句,尽管SELECT语句第一个出现,但是几乎总是最后被处理。 每个步骤都会产…

Linux下进程在后台可靠运行(nohup/)和前后台运行程序切换

我们经常会碰到这样的问题,用 telnet/ssh 登录了远程的 Linux 服务器,运行了一些耗时较长的任务, 结果却由于网络的不稳定导致任务中途失败。如何让命令提交后不受本地关闭终端窗口、网络断开连接的干扰呢? 下面举了一些例子&…

Java线程池(newCachedThreadPool、newFixedThreadPool、newScheduledThreadPool 、newSingleThreadExector )

1、new Thread的弊端 执行一个异步任务你还只是如下new Thread吗? new Thread(new Runnable() {Overridepublic void run() {// TODO Auto-generated method stub}} ).start(); 那你就out太多了,new Thread的弊端如下: a. 每次new Thread新建…