摘要
本文部分内容来源于网络,个人收集整理,请勿传播
- 跨站请求
- Cookie
- Session
- 缓存
- 分页
- 序列化
- 信号
- Mixin
- django邮件配置
- xss过滤
跨站请求伪造
django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddleware
来完成。而对于django中设置防跨站请求伪造功能有分为全局和局部。
- 全局
- 中间件
django.middleware.csrf.CsrfViewMiddleware
- 中间件
- 局部
@csrf_protect
,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。@csrf_exempt
,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。
注:
from django.views.decorators.csrf import csrf_exempt,csrf_protect
应用
普通表单
1 | # veiw中设置返回值: |
Ajax
对于传统的form,可以通过表单的方式将token再次发送到服务端,而对于ajax的话,使用如下方式。
1 | # view |
1 | # html |
Cookie
数据保存在客户端,可以减少服务端数据存储压力,但是不适合放敏感信息
获取Cookie
1 | request.COOKIES['key'] |
设置Cookie
1 | rep = HttpResponse(...) 或 rep = render(request, ...) |
由于cookie保存在客户端的电脑上,所以,JavaScript和jquery也可以操作cookie。
1 | <script src='/static/js/jquery.cookie.js'></script> |
Session
session与cookie相比保存在服务端,可以存放一些敏感信息
Django中默认支持Session,其内部提供了5种类型的Session供开发者使用:
- 数据库(默认)
- 缓存
- 文件
- 缓存+数据库
- 加密cookie
数据库Session
Django默认将Session数据存储在数据库中,即:django_session 表中。
request.session.set_expiry(60*10)
配置 settings.py
1 | # 引擎(默认) |
使用
1 | def index(request): |
缓存Session
1 | # 引擎 |
文件Session
1 | # 引擎 |
缓存+数据库Session
1 | SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db' |
加密cookie Session
1 | SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies' |
Session用户验证
1 | def login(func): |
缓存
由于Django是动态网站,所有每次请求均会去数据进行相应的操作,当程序访问量大时,耗时必然会更加明显,最简单解决方式是使用:缓存,缓存将一个某个views的返回值保存至内存或者memcache中,5分钟内再有人来访问时,则不再去执行view中的操作,而是直接从内存或者Redis中之前缓存的内容拿到,并返回。
Django中提供了6种缓存方式:
- 开发调试
- 内存
- 文件
- 数据库
- Memcache缓存(python-memcached模块)
- Memcache缓存(pylibmc模块)
- 通过第三方模块调用redis
开发调试
1 | # 此为开始调试用,实际内部不做任何操作 |
内存
1 | # 此缓存将内容保存至内存的变量中 |
文件
1 | # 此缓存将内容保存至文件 |
数据库
1 | # 此缓存将内容保存至数据库 |
Memcache缓存(python-memcached模块)
1 | # 此缓存使用python-memcached模块连接memcache |
Memcache缓存(pylibmc模块)
1 | # 此缓存使用pylibmc模块连接memcache |
Redis缓存(依赖:pip3 install django-redis)
1 | CACHES = { |
全站使用
1 | # 使用中间件,经过一系列的认证等操作, |
单独视图缓存
1 | # 方式一: |
局部视图使用
1 | # 引入TemplateTag |
序列化
关于Django中的序列化主要应用在将数据库中检索的数据返回给客户端用户,特别的Ajax请求一般返回的为Json格式。
serializers
1 | from django.core import serializers |
json.dumps
1 | import json |
由于json.dumps时无法处理datetime日期,所以可以通过自定义处理器来做扩展,如:
1 | import json |
信号
Django中提供了“信号调度”,用于在框架执行操作时解耦。通俗来讲,就是一些动作发生的时候,信号允许特定的发送者去提醒一些接受者。
1 | Model signals |
对于Django内置的信号,仅需注册指定信号,当程序执行相应操作时,自动触发注册函数:
1 | from django.core.signals import request_finished |
自定义信号
定义信号
1 | import django.dispatch |
注册信号
1 | def callback(sender, **kwargs): |
触发信号
1 | from 路径 import pizza_done |
由于内置信号的触发者已经集成到Django中,所以其会自动调用,而对于自定义信号则需要开发者在任意位置触发。
Mixin
什么是Mixin
在面向对象编程中,Mixin是一种类,这种类包含了其他类要使用的方法,但不必充当其他类的父类。其他类是如何获取Mixin中的方法因语言的不同而不同。所以有时候Mixin被描述为include(包含)
而不是 inheritance(继承)
。
Mixins鼓励代码重用,并且可以用于避免多重继承可能导致(”如钻石问题”)的继承歧义,或者解决一个缺乏对一种语言的多重继承的支持。mixin也可以被看作实现方法的接口。这种模式是强制依赖性反转原理的一个例子。
Mixin来源
mix-in是一种冰淇淋,提供一些基础口味(香草,巧克力等),在这种基础口味上可以添加其他食品(坚果,小饼干)。Mixin术语由此得来。
定义
Mixin是一种语言概念,允许程序员将一些代码注入到一个类中。Mixin编程是一种软件开发的风格,其中功能单元在一个类中创建,然后与其他类混合。
mixin类扮演父类的角色,包含其他类想要的功能。然后,一个子类可以继承或简单地重用此功能,但不能作为专业化的手段。通常,mixin将会将所需的功能导出到子类中,而不会创建一个单一的is a
关系。 这是mixin和继承的概念之间的重要区别,因为子类仍然可以继承父类的所有功能,但是,不必一定应用关于子对象”作为一种”父语义的语义。
优点
- 通过允许多个类使用通用功能,但没有多重继承的复杂语义,为多重继承提供了一种机制.
- 代码可重用性:当程序员希望在不同类之间共享功能时,Mixins很有用。不是一遍又一遍地重复相同的代码,通用功能可以简单地分组成一个混合,然后继承到需要它的每个类中。
- Mixins允许继承和使用只有父类的所需功能,不一定是父类的所有功能.
Django中Mixin和View组合技巧
- Mixin提供数据
- View提供模板和渲染
- 所以一般
get_context_data
在Mixin中 get(),post(),head()
在View中。- Mixin和View不是能随意组合的,必须要注意他们之间的方法的解析顺序,也就是MRO(method resolution order)。
关于MRO
1 | class TemplateView(TemplateResponseMixin, ContextMixin, View): |
- TemplateView继承自TemplateResponseMixin,ContextMixin以及View
- 通过get方法将上面的三个东西联系在一起
- TempalteResponseMixin和ContextMixin实现分别如下:
1 | class TemplateResponseMixin(object): |
Django中Mixin和View把原来的试图函数中的三个东西分开了,模板(TemplateResponseMixin),上下文数据(ContextMixin),负责将这些联系起来的一个东西(View)
- ContextMixin:直接就是一个get_context_data,用于返回context数据。
- View:会调用所有的get方法,post方法,View中是没有返回一个response的,所以光继承View的话,必须要重写get等,以返回一个response。
- TemplateResponseMixin:故名思议,这个Mixin会加入Template的基本信息,也就是template的名字。
但这里并不适合把这两个Mixin类解释为TemplatesView的父类,而更倾向于解释为提供接口及数据。把这两个类封装成mixin格式可以提高代码的重用性,所以可以说Mixin应该是一种设计思想。
Django中的实际应用
在FBV中,如果希望为视图的访问加上限制的话可以直接使用装饰器,但在CBV中就不能直接使用装饰器了。
比如说django auth
提供的默认的login_required
装饰器和permission_required
装饰器,在CBV中则为LoginRequiredMixin
以及PermissionRequiredMixin
。
这两个Mixin都继承于AccessMixin(导致了它们引起的异常跳转指向同一个url)
1 | class LoginRequiredMixin(AccessMixin): |
两个Mixin都实现了dispatch方法,并且在执行完以后调用的是按照MRO数组中的下一个类的dispatch方法,如果我们定义一个cbv,继承这两个mixin方法
1 | class MyView(LoginRequiredMixin, PermissionRequiredMixin, View) |
那么,dispatch
按照依次调用的顺序则是,LoginRequiredMixin
,PermissionRequiredMixn
,AccessMixin
(没有disptach
方法),View
。因此,基类View一定要放在多重继承的最后面,因为它的dispatch
方法调用就是代表业务逻辑的handler
了。
当LoginRequiredMixin
或者PermissionRequiredMixin
调用继承自AccessMixin
的handle_no_permission
方法时,如果raise_exception
被设置为True,会抛出一个PermissionDenied
的异常,否则跳转到login_url
。
邮件配置
1 | # 阿里云封掉了25端口,这里使用SSL/465发送邮件 |
xss过滤
- 通过使用BeautifulSoup过滤标签以及属性进行处理
1 | from bs4 import BeautifulSoup |
分页
Django内置分页
views
1 | from django.shortcuts import render |
html
1 |
|
扩展内置分页:views.py
1 | from django.shortcuts import render |
扩展内置分页:Html
1 | <!DOCTYPE html> |
自定义分页
分页功能在每个网站都是必要的,对于分页来说,其实就是根据用户的输入计算出应该在数据库表中的起始位置。
- 设定每页显示数据条数
- 用户输入页码(第一页、第二页…)
- 根据设定的每页显示条数和当前页码,计算出需要取数据表的起始位置
- 在数据表中根据起始位置取值,页面上输出数据
需要在页面上显示分页的页面。如:[上一页][1][2][3][4][5][下一页]
- 设定每页显示数据条数
- 用户输入页码(第一页、第二页…)
- 设定显示多少页号
- 获取当前数据总条数
- 根据设定显示多少页号和数据总条数计算出,总页数
- 根据设定的每页显示条数和当前页码,计算出需要取数据表的起始位置
- 在数据表中根据起始位置取值,页面上输出数据
- 输出分页html,如:
[上一页][1][2][3][4][5][下一页]
分页实例
1 | #!/usr/bin/env python |
总结,分页时需要做三件事:
- 创建处理分页数据的类
- 根据分页数据获取数据
- 输出分页HTML,即:
[上一页][1][2][3][4][5][下一页]