一、中间件 

  中间件是一类,在请求到来和结束后,django会根据自己的规则在合适的时机执行中间件中相应的方法;在django项目的settings模块中,有一个 MIDDLEWARE 变量,其中每一个元素就是一个中间件。
# MIDDLEWARE = [
# 'django.middleware.security.SecurityMiddleware',
# 'django.contrib.sessions.middleware.SessionMiddleware',
#                                 ......
# 'django.middleware.clickjacking.XFrameOptionsMiddleware',
# ]

中间件中可以定义四个方法:
①process_request(self,request)       请求来时执行,不写时直接跳过,执行下一个中间件;当有return HttpResonse时,下面中间件不再执行
②process_view(self, request, callback, callback_args, callback_kwargs) 先执行process_request,执行完后,再从起始执行proces_view
③process_template_response(self,request,response)   如果Views中的函数返回的对象中,具有render方法,此方法执行
④process_exception(self, request, exception)   异常触发执行,当views.py函数执行出错后,此方法执行;出错时,最低层的exception优先级最高,执行最近的一个,然后执行respnse方法
⑤process_response(self, request, response)       请求返回时执行,不写时直接跳过,执行下一个中间件;当有return HttpResonse时,会替换原数据
以上方法的返回值可以是None和HttpResonse对象,如果是None,则继续按照django定义的规则向下执行,如果是HttpResonse对象,则直接将该对象返回给用户。
注:Django版本1.10之后 直接执行同级的process_response,而不是从最低层process_response开始执行

2、自定义中间件
Django主目录下创建middleware目录(名字任意),在目录下创建m.py文件
① process_request、process_response

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse class Row1(MiddlewareMixin):
def process_request(self,request):
print("王森1")
# return HttpResponse("DDDD")
def process_response(self,request,response):
print("扛把子1")
return response class Row2(MiddlewareMixin):
def process_request(self,request):
print("王森2")
def process_response(self, request, response):
print("扛把子3")
return response class Row3(MiddlewareMixin):
def process_request(self,request):
print("王森3")
def process_response(self, request, response):
print("扛把子3")
return response

#xxoo.py(在新建Middle文件中自定义中间件类)

from django.shortcuts import render,redirect,HttpResponse
def test(request):
print('走你')

#views.py

from django.middleware.csrf import  CsrfViewMiddleware
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'middleware.m.Row1', #
'middleware.m.Row2', #
'middleware.m.Row3', # from app01 import views
urlpatterns = [
url(r'^test/$', views.test),
]

#settings.py(注册中间件)

王森1
王森2
王森3
走你
扛把子3
扛把子3
扛把子1

#打印结果

② process_view

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse class Row1(MiddlewareMixin):
def process_request(self,request):
print("王森1")
def process_view(self, request, view_func, view_func_args, view_func_kwargs):
print("James1")
def process_response(self,request,response):
print("扛把子1")
return response class Row2(MiddlewareMixin):
def process_request(self,request):
print("王森2")
def process_view(self, request, view_func, view_func_args, view_func_kwargs):
print("James2")
def process_response(self, request, response):
print("扛把子3")
return response class Row3(MiddlewareMixin):
def process_request(self,request):
print("王森3")
def process_view(self, request, view_func, view_func_args, view_func_kwargs):
print("James3")
def process_response(self, request, response):
print("扛把子3")
return response

#xxoo.py(在新建Middle文件中自定义中间件类)

王森1
王森2
王森3
James1
James2
James3
走你
扛把子3
扛把子3
扛把子1

#打印结果

二、CSRF 

1、概述
  CSRF(Cross Site Request Forgery)跨站点伪造请求,举例来讲,某个恶意的网站上有一个指向你的网站的链接,如果某个用户已经登录到你的网站上了,那么当这个用户点击这个恶意网站上的那个链接时,就会向你的网站发来一个请求,你的网站会以为这个请求是用户自己发来的,其实呢,这个请求是那个恶意网站伪造的。
  为了避免上面情况的出现,Django引用了CSRF防护机制;Django第一次响应来自某个客户端的请求时,会在服务器端随机生成一个 token,并把这个 token 放在 cookie 里。然后每次 POST 请求都会带上这个 token,这样就能避免被 CSRF 攻击。如果POST请求中没有token随机字符串,则返回403拒绝服务
---在返回的 HTTP 响应的 cookie 里,django 会为你添加一个 csrftoken 字段,其值为一个自动生成的 token
---在所有的 POST 表单时,必须包含一个 csrfmiddlewaretoken 字段 (只需要在模板里加一个 tag, django 就会自动帮你生成,见下面)
---在处理 POST 请求之前,django 会验证这个请求的 cookie 里的 csrftoken 字段的值和提交的表单里的 csrfmiddlewaretoken 字段的值是否一样。如果一样,则表明这是一个合法的请求,否则,这个请求可能是来自于别人的 csrf 攻击,返回 403 Forbidden。
---在所有 ajax POST 请求里,添加一个 X-CSRFTOKEN header,其值为 cookie 里的 csrftoken 的值
下面我们需要在settings.py中把中间件django.middleware.csrf.CsrfViewMiddleware启用:

MIDDLEWARE = [
'django.middleware.csrf.CsrfViewMiddleware',
]

#settings.py

局部使用方式:
@csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。
@csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。

CBA中的使用方式:

from django.utils.decorators import method_decorator
class AssetView(View):
@method_decorator(csrf_exempt) #必须加到dispatch上,get、post上都不好使
def dispatch(self, request, *args, **kwargs):
return super(AssetView, self).dispatch(request, *args, **kwargs)

2、Form表单/Ajax 提交POST请求

from django.shortcuts import render,HttpResponse,redirect

def login(request):
if request.method == 'GET':
return render(request,'login.html')
elif request.method == 'POST':
user = request.POST.get('user')
pwd = request.POST.get('pwd')
if user == 'root' and pwd == "":
# 生成随机字符串
# 写到用户浏览器Cookie
# 保存到Session中
# 在随机字符串对应的字典中设置相关内容...
request.session['username'] = user
request.session['if_login'] = True #可不加 直接判断username也可以
if request.POST.get('session') == '': #单独设置超时时间,当前session生效,不影响全局
request.session.set_expiry(10) #10秒
return redirect('/index/')
else:
return redirect('/login/') def index(request):
# 获取当前用户的随机字符串
# 根据随机字符串获取对应信息
if request.session.get('if_login'):
return render(request, 'index.html')
else:
return redirect('/login/')

#views.py

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/login/" method="post">
{% csrf_token %} ##
<input type="text" name="user" />
<input type="text" name="pwd" />
<input type="checkbox" name="session" value=""/> 保存1个月
<input type="submit" value="提交" />
</form>
</body>
</html>

#login.html(Form表单提交POST请求)

{# Ajax提交时要添加headers值 #}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/login/" method="post">
{% csrf_token %} ##
<input type="text" name="user" />
<input type="text" name="pwd" />
<input type="checkbox" name="session" value=""/> 保存1个月
<input id='btn' type="button" value="Ajax提交" />
</form>
<script src="/static/jquery-1.12.4.js"></script> #与下面的顺序不要颠倒
<script src="/static/jquery.cookie.js"></script>
<script>
$(function () {
$('#btn').click(function () {
$.ajax({
url:'/login/',
type:'POST',
data:{'user':'root','pwd':''},
headers:{'X-CSRFtoken':$.cookie('csrftoken')},##
success:function (arg) {
}
})
})
})
</script>
</body>
</html>

#login.html(Ajax表单提交POST请求)

往往一个程序不止一个Ajax请求,所以我们需要对每个Ajax请求都添加headers请求头,这样未免增加很多工作量;这时就需要做全局设置,不必每个都添加请求头

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/login/" method="post">
{% csrf_token %}
<input type="text" name="user" />
<input type="text" name="pwd" />
<input type="checkbox" name="session" value=""/> 保存1个月
<input id='btn' type="button" value="Ajax提交" />
</form>
<script src="/static/jquery-1.12.4.js"></script>
<script src="/static/jquery.cookie.js"></script>
<script>
$(function () {
{# 全局配置,所有Ajax请求都先执行下面操作#}
$.ajaxSetup({ ##
beforeSend:function (xhr,settings) { ##
xhr.setRequestHeader('X-CSRFtoken',$.cookie('csrftoken')); ##
} ##
}); ## $('#btn').click(function () {
$.ajax({
url:'/login/',
type:'POST',
data:{'user':'root','pwd':''},
success:function (arg) { }
})
})
})
</script>
</body>
</html>

#login.html(全局生效)

<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
{% csrf_token %} <input type="button" onclick="Do();" value="Do it"/> <script src="/static/plugin/jquery/jquery-1.8.0.js"></script>
<script src="/static/plugin/jquery/jquery.cookie.js"></script>
<script type="text/javascript">
var csrftoken = $.cookie('csrftoken'); ## function csrfSafeMethod(method) { ##
// these HTTP methods do not require CSRF protection ##
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); ##GET|HEAD|OPTIONS|TRACE 四种请求
} ##
$.ajaxSetup({ ##
beforeSend: function(xhr, settings) { ##
if (!csrfSafeMethod(settings.type) && !this.crossDomain) { ##
xhr.setRequestHeader("X-CSRFToken", csrftoken); ##
} ##
} ##
}); ##
function Do(){ $.ajax({
url:"/app01/test/",
data:{id:1},
type:'POST',
success:function(data){
console.log(data);
}
}); }
</script>
</body>
</html>

#官方使用示例.html(所有方式的请求都添加csrf)

三、缓存 

由于Django是动态网站,所有每次请求均会去数据进行相应的操作,当程序访问量大时,耗时必然会更加明显,最简单解决方式是使用:缓存,缓存将一个某个views的返回值保存至内存或者memcache中,5分钟内再有人来访问时,则不再去执行view中的操作,而是直接从内存或者Redis中之前缓存的内容拿到,并返回。

Django中提供了6种缓存方式:
        --开发调试
        --内存
        --文件
        --数据库
        --Memcache缓存(python-memcached模块、pylibmc模块)

① 开发调试配置

# 此为开始调试用,实际内部不做任何操作
# 配置:
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.dummy.DummyCache', # 引擎
'TIMEOUT': 300, # 缓存超时时间(默认300,None表示永不过期,0表示立即过期)
'OPTIONS':{
'MAX_ENTRIES': 300, # 最大缓存个数(默认300)
'CULL_FREQUENCY': 3, # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
},
'KEY_PREFIX': '', # 缓存key的前缀(默认空)
'VERSION': 1, # 缓存key的版本(默认1)
'KEY_FUNCTION' 函数名 # 生成key的函数(默认函数会生成为:【前缀:版本:key】)
}
} # 自定义key
def default_key_func(key, key_prefix, version):
"""
Default function to generate keys. Constructs the key used by all other methods. By default it prepends
the `key_prefix'. KEY_FUNCTION can be used to specify an alternate
function with custom key making behavior.
"""
return '%s:%s:%s' % (key_prefix, version, key) def get_key_func(key_func):
"""
Function to decide which key function to use. Defaults to ``default_key_func``.
"""
if key_func is not None:
if callable(key_func):
return key_func
else:
return import_string(key_func)
return default_key_func

#开发

② 内存配置

# 此缓存将内容保存至内存的变量中
# 配置:
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
'LOCATION': 'unique-snowflake',
}
} # 注:其他配置同开发调试版本

#内存

③ 文件配置

# 此缓存将内容保存至文件
# 配置: CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
'LOCATION': '/var/tmp/django_cache',
}
}
# 注:其他配置同开发调试版本

#文件

④ 数据库配置

# 此缓存将内容保存至数据库

    # 配置:
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
'LOCATION': 'my_cache_table', # 数据库表
}
} # 注:执行创建表命令 python manage.py createcachetable

#数据库

⑤ Memcache缓存

CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': '127.0.0.1:11211',
}
} CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': 'unix:/tmp/memcached.sock',
}
} CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': [
'172.19.26.240:11211',
'172.19.26.242:11211',
]
}
} CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': [
# 权重
('172.19.26.240:11211',1),
('172.19.26.242:11211',15)
]
}
}

#python-memcached模块

# 此缓存使用pylibmc模块连接memcache

    CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
'LOCATION': '127.0.0.1:11211',
}
} CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
'LOCATION': '/tmp/memcached.sock',
}
} CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
'LOCATION': [
'172.19.26.240:11211',
'172.19.26.242:11211',
]
}
}

#pylibmc模块

2、应用(静态文件的数据缓存,动态的文件数据不缓存)
① 全站使用

#全局生效
使用中间件,经过一系列的认证等操作,如果内容在缓存中存在,则使用FetchFromCacheMiddleware获取内容并返回给用户,当返回给用户之前,判断缓存中是否已经存在,如果不存在则UpdateCacheMiddleware会将缓存保存至缓存,从而实现全站缓存 MIDDLEWARE = [
# 写到最上面
'django.middleware.cache.UpdateCacheMiddleware',
# 其他中间件... # 写到最下面
'django.middleware.cache.FetchFromCacheMiddleware',
]

#全局生效

② 单独视图缓存

方式一:
from django.views.decorators.cache import cache_page @cache_page(60 * 15)
def my_view(request):
... 方式二:
from django.views.decorators.cache import cache_page urlpatterns = [
url(r'^foo/([0-9]{1,2})/$', cache_page(60 * 15)(my_view)),
]

#单独方法生效

③ 局部视图使用

    a. 引入TemplateTag

        {% load cache %}

    b. 使用缓存

        {% cache 5000 缓存key %}
缓存内容
{% endcache %}

#html单独部分生效

3、单独视图缓存示例(cache方法处理的请求,都进行缓存10秒)

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>{{ ctime }}</h1>
<h1>{{ ctime }}</h1>
<h1>{{ ctime }}</h1>
</body>
</html>

#cache.html

CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
'LOCATION': os.path.join(BASE_DIR,'cache'),
}
}

#settings.py

from django.views.decorators.cache import cache_page
@cache_page(10) # 装饰cache方法 #10S失效比默认配置的300S级别高
def cache(request):
import time
ctime = time.time()
return render(request,'cache.html',{'ctime':ctime})

#views.py

4、局部视图示例(缓存html文件某一部分)

{% load cache %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>{{ ctime }}</h1>
<h1>{{ ctime }}</h1>
{% cache 10 c1 %} #缓存10秒;c1为缓存key
<h1>{{ ctime }}</h1>
{% endcache %}
</body>
</html>

#cache.html

CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
'LOCATION': os.path.join(BASE_DIR,'cache'),
}
}

#settings.py

def cache(request):
import time
ctime = time.time()
return render(request,'cache.html',{'ctime':ctime})

#views.py

5、全局生效

MIDDLEWARE = [
'django.middleware.cache.UpdateCacheMiddleware',
...........
'django.middleware.cache.FetchFromCacheMiddleware',
]

#settings.py

其余文件都一致,全局优先级大;请求流程-->使用中间件,经过一系列的认证等操作,如果内容在缓存中存在,则使用FetchFromCacheMiddleware获取内容并返回给用户,如果不存在则接着往下走,执行views函数,最后经过UpdateCacheMiddleware会将缓存保存至缓存,从而实现全站缓存。

Python学习笔记整理总结【Django】:中间件、CSRF、缓存的更多相关文章

  1. python学习笔记整理——字典

    python学习笔记整理 数据结构--字典 无序的 {键:值} 对集合 用于查询的方法 len(d) Return the number of items in the dictionary d. 返 ...

  2. Python学习笔记整理总结【Django】【MVC/MTV/路由分配系统(URL)/视图函数 (views)/表单交互】

     一.Web框架概述  Web框架本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端. #!/usr/bin/env python # -*- coding:utf-8 ...

  3. Python学习笔记整理总结【Django】:Model操作(一)

    Model操作(一) 一.Django ORM基本配置 ORM:关系对象映射(Object Relational Mapping,简称ORM)db Frist:到目前为止,当我们的程序涉及到数据库相关 ...

  4. python学习笔记整理——集合 set

    python学习整理笔记--集合 set 集合的用途:成员测试和消除重复的条目,进行集合运算 注意:花括号或set()函数可以用于创建集合. 注意:若要创建一个空的集合你必须使用set(),不能用{} ...

  5. python 学习笔记二十 django项目bbs论坛

    项目:开发一个简单的BBS论坛 需求: 整体参考“抽屉新热榜” + “虎嗅网” 实现不同论坛版块 帖子列表展示 帖子评论数.点赞数展示 在线用户展示 允许登录用户发贴.评论.点赞 允许上传文件 帖子可 ...

  6. python 学习笔记十五 django基础

    Python的WEB框架有Django.Tornado.Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了ORM.模型绑定.模板引擎.缓存.Session等诸多功能. ...

  7. python学习笔记整理——元组tuple

    Python 文档学习笔记2 数据结构--元组和序列 元组 元组在输出时总是有括号的 元组输入时可能没有括号 元组是不可变的 通过分拆(参阅本节后面的内容)或索引访问(如果是namedtuples,甚 ...

  8. python学习笔记整理——列表

    Python 文档学习笔记 数据结构--列表 列表的方法 添加 list.append(x) 添加元素 添加一个元素到列表的末尾:相当于a[len(a):] = [x] list.extend(L) ...

  9. Python学习笔记整理总结【Django】:Model操作(二)

    1.操作汇总 # 增 # # models.Tb1.objects.create(c1='xx', c2='oo') 增加一条数据,可以接受字典类型数据 **kwargs # obj = models ...

随机推荐

  1. 使用react定义组件的两种方式

    react组件的两种方式:函数定义,类定义 在定义一个组件之前,首先要明白一点:react元素(jsx)是react组件的最基本的组成单位 组件要求: 1,为了和react元素进行区分,组件名字首必须 ...

  2. python 21 面向对象

    目录 1. 面向对象初步认识 2. 面向对象的结构 3. 从类名的角度研究类 3.1 类名操作类中的属性 3.2 类名调用类中的方法 4. 从对象的角度研究类 4.1 类名() 4.2 对象操作对象空 ...

  3. ionic App 解决android端在真机上 tab处于顶部的Bug

    在app.js 页面中添加以下代码 .config(function($stateProvider, $urlRouterProvider,$ionicConfigProvider) { $ionic ...

  4. bzoj 1146 网络管理Network (CDQ 整体二分 + 树刨)

    题目传送门 题意:求树上路径可修改的第k大值是多少. 题解:CDQ整体二分+树刨. 每一个位置上的数都会有一段持续区间 根据CDQ拆的思维,可以将这个数拆成出现的时间点和消失的时间点. 然后通过整体二 ...

  5. poj 3616 Milking Time (基础dp)

    题目链接 http://poj.org/problem?id=3616 题意:在一个农场里,在长度为N个时间可以挤奶,但只能挤M次,且每挤一次就要休息t分钟: 接下来给m组数据表示挤奶的时间与奶量求最 ...

  6. CF 450E Jzzhu and Apples 数学+模拟

    E. Jzzhu and Apples time limit per test 1 second memory limit per test 256 megabytes input standard ...

  7. yzoj P2344 斯卡布罗集市 题解

    共t条街对于每一条街上有n个店铺(n可能不相同),每次只能选两端第一个营业的店铺采购,采购第i个店铺会获得幸福度ai,采购完后,这个店铺和它相邻的店铺便会关门,问最大幸福度? 考场想了一下dp,一开始 ...

  8. JS-特效 ~ 02. 屏幕滚动事件、 DTD、scroll、顶部悬浮导航、两侧跟随广告、返回顶部小火煎

    ceil 向上取整 floor 向下取整 round 四舍五入 缓动动画 动画原理 = 盒子位置 + 步长 清除定时器 步长越来越小 盒子位置 = 盒子本身位置 + (目标位置-本身位置)/n(最好为 ...

  9. C#客户端程序Visual Stadio远程调试

    一,需求来源 在开发过程中,可能会要使用Win7 ,Win8 ,Win10等不同版本的系统去做兼容性调试,也有时候会去针对特别的显卡,无线网卡等等硬件设备的机器做优化,有一种较优的方案,那就是使用Vi ...

  10. Helm 从入门到实践 | 从 0 开始制作一个 Helm Charts

    本周 Helm 官方发布博客,指导用户从 v2 迁移到 v3,这标志 Helm 逐渐走向成熟.早在今年 6 月,阿里云就正式发布了国内首个 Helm Hub 中国镜像站:开放云原生应用中心 - Clo ...