Assert 可以说得上是 Pytest 的灵魂。比起其他测试框架,Pytest 的断言机制非常简洁,它屏蔽了表达式的类型、断言的类型,只需使用 assert 关键字( 而不是 AssertionTrue 之类函数) 即可完成测试用例的检查。
Django: Cookies & Session
Cookies 和 Session 都是用于实现HTTP 持久化的工具。他们的不同处在于 Cookie 是放在客户端(浏览器)上的文本;Session 是储存在服务器上的资源。
在大部分情况下,他们的作用一样 —— Cookie(Session)是一串键值对,通过在服务器中检索键值对中的值,来获取用户登录状态、确定用户权限或返回用户请求的资源。由于HTTP 协议是无状态的,如果没有cookie(session) ,同一个用户的两次请求,服务器会认为来自不同用户,有些状态就没法保持(比如:用户在A页面将商品加入购物车后点进购物车页面)。
在大多数情况下,他们可以单独使用:
- 仅使用cookie:在头部字段携带cookie,服务器端取cookie值,返回相应资源;
- 仅使用session: 在头部字段携带 XMLHTTPRequest 对象索引session 位置;
不过在Django 中,Session 完全基于 Cookie 才能使用。以下是他们的一些细节。
COOKIES
在Django 中,View 获取cookie 的方法是调用request.COOKIES['cookie_name']。
COOKIES 位于HTTPRequest 类中,是字典类型变量。Request 的生命周期是这样:
从浏览器传入 -> WSGI -> 生成HTTPRequest obj -> 经过中间件 -> URLs 路由 -> View
COOKIES 是在生成HTTPRequest 类时被初始化的。
在最初对网页发起Request 请求时,COOKIES 是空的。网页回传Response 时,通过set_cookie(),在返回头中加入Set-Cookie 字段。随后再次请求同一个域才有值。
Cookie 最初应该是字符串形式,为了让它变成字典型,Django 使用 parse_cookie()将其转换,源码如下:
1 | # django/http/cookies |
此时客户端已经得到了cookie ,接下来就要用它和Session 交互了。
Session
在Django 中,使用了专门的Middleware 支持Session。编辑设置中的 MIDDLEWARE,并确保他包含了 'django.contrib.sessions.middleware.SessionMiddleware'。
在SessionMiddleware 中,通过process_request 与process_response 修改 request 和 response 的session 属性。
当传入Request 时,从COOKIES 取出setting.py约定的SESSION_COOKIE_NAME,通过这个值从Session引擎中取出相应的Session 对象,赋值 reqeust.session 。所以说,在Django 中,Session 和 Cookie 通过 SESSION_COOKIE_NAME 字段的值联结。代码如下:
1 | def process_request(self, request): |
存储Session 的可能是数据库、文件系统或缓存,Session引擎提供了一套屏蔽不同类型操作的API。
当传出Response 时,process_response 检查 request.session 的三个属性,分别是accessed empty modify 。当empty = True ,证明在刚刚的View 中,用户登出了,此时应当删除Cookie,返回Response (但还不是删除Session 的时候,只有Session 内容全为空时才能删掉)。当accessed = True,用当前的Cookie 内容更新 Vary头;而当 modify = True 刷新的过期时间(此时还没有保存!),随后检查HTTP状态码,如果返回码不是500,保存当前session 并使用该session 内容更新Cookie ,否则不保存也不更新。最后返回Response 。
process_response 接收三个参数:self、request、response,request是上一个中间件发来的,里面包含session,response是view通过中间件一层一层传过来的,里面包含cookie。
process_response伪代码:
def process_response(self, request, response):
get request.session.access/ modify/ empty
if empty:
response.delete_cookie(SESSION_COOKIE_NAME )
else:
if accessed:
patch_vary_headers(response, ('Cookie',))
if modified and not empty:
use session's attrs update expire & max_age
if response.status_code != 500:
request.session.save()
response.set_cookie(expire and max_age)
return response
Django 使用定时任务检查保质期
记录了在Django 中设置定时任务的过程。
Socket:多人聊天室
为了巩固网络编程知识点,写了一个不带界面的多人聊天程序
RESTful web Service:Django DELETE 请求
之前读了一些关于REST 风格的文章,觉得蛮好就打算在本次毕设中用用,Django 也支持不同请求方式接口,之前用get()、post()都用得好好的,结果本次就踩坑了,记录一下爬出来的过程。
Python C++扩展
前置:准备工作