Python公开课 - Django自动添加Last-Modified和ETag
什么是Last-Modified和ETag
Last-Modified
在浏览器第一次请求某一个URL时,正常情况下服务器端的返回状态码 HTTP 200,内容是请求的资源,同时有一个Last-Modified的属性标记此文件在服务期端最后被修改的时间,格式类似这样:
Last-Modified: Fri, 12 May 2018 18:53:33 GMT
当客户端第二次请求此URL时,根据HTTP协议的规定,浏览器会向服务器传送 If-Modified-Since 报头,询问该时间之后文件是否有被修改过:
If-Modified-Since: Fri, 12 May 2006 18:53:33 GMT
如果服务器端的资源没有变化,则自动返回 HTTP 304 状态码,内容为空,这样就节省了传输数据量。当服务器端代码发生改变或者重启服务器时,则重新发出资源,返回和第一次请求时类似。
从而保证不向客户端重复发出资源,也保证当服务器有变化时,客户端能够得到最新的资源。
ETag
HTTP 协议规格说明定义ETag为“被请求变量的实体值”。你也可以将ETag理解为一个可以与Web资源关联的记号(token)。
典型的Web资源可以一个Web页,但也可能是JSON或XML文档。
服务器单独负责判断记号是什么及其含义,并在HTTP响应头中将其传送到客户端,以下是服务器端返回的格式:
ETag: "50b1c1d4f775c61:df3"
客户端的查询更新格式是这样的:
If-None-Match: W/"50b1c1d4f775c61:df3"
如果ETag没改变,则返回状态304然后不返回,这也和Last-Modified一样。
Django中如何配置Last-Modified和ETag
在Django项目里,对于一个响应或者页面返回来说,一般都是通过view
来进行处理,它会提供两个HTTP头信息:ETag和Last-Modified。
这两个头信息可以在view
自行编码操作,也可以通过ConditionalGetMiddleware
中间件来设置ETag,在Django2.2版本中,默认配置已经含有了。
Django中有三个decorator,可以为响应添加Last-Modified和ETag。
- condition(etag_func=None, last_modified_func=None)
- etag(etag_func)
- last_modified(last_modified_func)
要注意的是,官网给的使用方法都是针对function-based view,如果你使用的是class-based view,需要在url配置中调用decorator,示例如下:
def etag_func(request, *args, **kwargs):
pk = kwargs['pk']
try:
obj = Article.objects.get(id=pk)
GMT_FORMAT = '%a, %d %b %Y %H:%M:%S GMT'
last_modified = obj.update_time.strftime(GMT_FORMAT)
m = hashlib.md5()
m.update(last_modified.encode('utf8'))
return m.hexdigest()
except Article.DoesNotExist:
return None
def last_modified_func(request, *args, **kwargs):
pk = kwargs['pk']
try:
obj = Article.objects.get(id=pk)
return obj.update_time
except Article.DoesNotExist:
return None
urlpatterns = [
url('^/detail-(?P<pk>\d+).html', condition(etag_func=etag_func, last_modified_func=last_modified_func)(views.Detail.as_view())),
]
效果如图所示: