中间件

  解析

django 中的中间件(middleware),在django中,中间件其实就是一个类,在请求到来和结束后,

django会根据自己的规则在合适的时机执行中间件中相应的方法。

在django项目的settings模块中,有一个 MIDDLEWARE_CLASSES 变量,

其中每一个元素就是一个中间件,

  1. MIDDLEWARE = [
  2. 'django.middleware.security.SecurityMiddleware',
  3. 'django.contrib.sessions.middleware.SessionMiddleware',
  4. 'django.middleware.common.CommonMiddleware',
  5. # 'django.middleware.csrf.CsrfViewMiddleware', # 跨站请求伪造
  6. 'django.contrib.auth.middleware.AuthenticationMiddleware',
  7. 'django.contrib.messages.middleware.MessageMiddleware',
  8. 'django.middleware.clickjacking.XFrameOptionsMiddleware',
  9. ]

以上方法的返回值可以是None和HttpResonse对象,如果是None,则继续按照django定义的规则向下执行,

如果是HttpResonse对象,则直接将该对象返回给用户。

  流程图

上面的流程图可能有些乱,为了解流程花的草图;

上面是Django 1.9版本的流程图,到django 1.10就变了;

变成了request在相对应的response中找。

  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3. from django.shortcuts import HttpResponse
  4.  
  5. class test1Middleware(object):
  6.  
  7. def process_request(self, request):
  8. print('')
  9.  
  10. def process_view(self, request, callback, callback_args, callback_kwargs):
  11. print('process_view1')
  12.  
  13. def process_response(self, request, response):
  14. print('response 111111')
  15. return response
  16.  
  17. def process_template_response(self, request, response):
  18. print('template1')
  19.  
  20. return response
  21.  
  22. def process_exception(self, request, exception):
  23. print('ex1')
  24.  
  25. class test2Middleware(object):
  26.  
  27. def process_request(self, request):
  28.  
  29. #if request.META['REMOTE_ADDR'] in ['1.1.1.1','1.1.1.2']:
  30. # return HttpResponse('SB')
  31. # return HttpResponse('SB')
  32. print('')
  33.  
  34. def process_view(self, request, callback, callback_args, callback_kwargs):
  35. print('process_view2')
  36.  
  37. def process_template_response(self, request, response):
  38. print('template2')
  39.  
  40. return response
  41. def process_exception(self, request, exception):
  42. print('ex2')
  43.  
  44. class test3Middleware(object):
  45.  
  46. def process_request(self, request):
  47. print('')
  48.  
  49. def process_response(self, request, response):
  50. print('response 33333')
  51. return response
  52.  
  53. def process_view(self, request, callback, callback_args, callback_kwargs):
  54. print('process_view3')
  55.  
  56. def process_template_response(self, request, response):
  57. print('template3')
  58. return response
  59.  
  60. def process_exception(self, request, exception):
  61. print('ex3')
  62. return HttpResponse('')

test.py

  自定义中间件

1、创建中间件的类

  1. class RequestExeute(object):
  2.  
  3. def process_request(self,request):
  4. pass
  5. def process_view(self, request, callback, callback_args, callback_kwargs):
  6. i =1
  7. pass
  8. def process_exception(self, request, exception):
  9. pass
  10.  
  11. def process_response(self, request, response):
  12. return response

2、注册中间件

  1. MIDDLEWARE_CLASSES = (
  2. 'django.contrib.sessions.middleware.SessionMiddleware',
  3. 'django.middleware.common.CommonMiddleware',
  4. 'django.middleware.csrf.CsrfViewMiddleware',
  5. 'django.contrib.auth.middleware.AuthenticationMiddleware',
  6. 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
  7. 'django.contrib.messages.middleware.MessageMiddleware',
  8. 'django.middleware.clickjacking.XFrameOptionsMiddleware',
  9. 'wupeiqi.middleware.auth.RequestExeute',
  10. )

  

缓存

  解析

由于Django是动态网站,一般来说需要实时地生成访问的网页,展示给访问者,这样内容可以随时变化,

但是从数据库读多次把所需要的数据取出来,要比从内存或者硬盘中读出来 付出的成本大很多。

最简单解决方式是使用:缓存,缓存将一个某个views的返回值保存至内存或者Redis中,一定时间内再有人来访问时,

则不再去执行view中的操作,而是直接从内存或者Redis中之前缓存的内容拿到,并返回。

Django中提供6种缓存方式:

  开发调试

  内存

  文件

  数据库

  Memcache缓存(python-memcached模块)

  Memcache缓存(pylibmc模块)

  配置

a、开发调试

  1. # 此为开始调试用,实际内部不做任何操作
  2. # 配置:
  3. CACHES = {
  4. 'default': {
  5. 'BACKEND': 'django.core.cache.backends.dummy.DummyCache', # 引擎
  6. 'TIMEOUT': 300, # 缓存超时时间(默认300,None表示永不过期,0表示立即过期)
  7. 'OPTIONS':{
  8. 'MAX_ENTRIES': 300, # 最大缓存个数(默认300)
  9. 'CULL_FREQUENCY': 3, # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
  10. },
  11. 'KEY_PREFIX': '', # 缓存key的前缀(默认空)
  12. 'VERSION': 1, # 缓存key的版本(默认1)
  13. 'KEY_FUNCTION' 函数名 # 生成key的函数(默认函数会生成为:【前缀:版本:key】)
  14. }
  15. }
  16.  
  17. # 自定义key
  18. def default_key_func(key, key_prefix, version):
  19. """
  20. Default function to generate keys.
  21.  
  22. Constructs the key used by all other methods. By default it prepends
  23. the `key_prefix'. KEY_FUNCTION can be used to specify an alternate
  24. function with custom key making behavior.
  25. """
  26. return '%s:%s:%s' % (key_prefix, version, key)
  27.  
  28. def get_key_func(key_func):
  29. """
  30. Function to decide which key function to use.
  31.  
  32. Defaults to ``default_key_func``.
  33. """
  34. if key_func is not None:
  35. if callable(key_func):
  36. return key_func
  37. else:
  38. return import_string(key_func)
  39. return default_key_func

b、内存

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

c、文件

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

d、数据库

  1. # 此缓存将内容保存至数据库
  2.  
  3. # 配置:
  4. CACHES = {
  5. 'default': {
  6. 'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
  7. 'LOCATION': 'my_cache_table', # 数据库表
  8. }
  9. }
  10.  
  11. # 注:执行创建表命令 python manage.py createcachetable

e、Memcache缓存(python-memcached模块)

  1. # 此缓存使用python-memcached模块连接memcache
  2.  
  3. CACHES = {
  4. 'default': {
  5. 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
  6. 'LOCATION': '127.0.0.1:11211',
  7. }
  8. }
  9.  
  10. CACHES = {
  11. 'default': {
  12. 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
  13. 'LOCATION': 'unix:/tmp/memcached.sock',
  14. }
  15. }
  16.  
  17. CACHES = {
  18. 'default': {
  19. 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
  20. 'LOCATION': [
  21. '172.19.26.240:11211',
  22. '172.19.26.242:11211',
  23. ]
  24. }
  25. }

f、Memcache缓存(pylibmc模块)

  1. # 此缓存使用pylibmc模块连接memcache
  2.  
  3. CACHES = {
  4. 'default': {
  5. 'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
  6. 'LOCATION': '127.0.0.1:11211',
  7. }
  8. }
  9.  
  10. CACHES = {
  11. 'default': {
  12. 'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
  13. 'LOCATION': '/tmp/memcached.sock',
  14. }
  15. }
  16.  
  17. CACHES = {
  18. 'default': {
  19. 'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
  20. 'LOCATION': [
  21. '172.19.26.240:11211',
  22. '172.19.26.242:11211',
  23. ]
  24. }
  25. }

  应用 

a. 全站使用

  1. 使用中间件,经过一系列的认证等操作,如果内容在缓存中存在,则使用FetchFromCacheMiddleware获取内容并返回给用户,
    当返回给用户之前,判断缓存中是否已经存在,如果不存在则UpdateCacheMiddleware会将缓存保存至缓存,从而实现全站缓存
  2.  
  3. MIDDLEWARE = [
  4. 'django.middleware.cache.UpdateCacheMiddleware',
  5. # 其他中间件...
  6. 'django.middleware.cache.FetchFromCacheMiddleware',
  7. ]
  8.  
  9. CACHE_MIDDLEWARE_ALIAS = ""
  10. CACHE_MIDDLEWARE_SECONDS = ""
  11. CACHE_MIDDLEWARE_KEY_PREFIX = ""

b. 单独视图缓存

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

  示例:

  1. from django.shortcuts import render,HttpResponse,HttpResponseRedirect
  2. import time
  3. # from django_nanian import pizza_done
  4. from django.views.decorators.cache import cache_page
  5.  
  6. class Response:
  7. def __init__(self, request, html, *args, **kwargs):
  8. self.request = request
  9. self.args = args
  10. self.html = html
  11. self.kwargs = kwargs
  12.  
  13. def render(self, *args, **kwargs):
  14. return render(self.request, self.html, *self.args, **self.kwargs)
  15. # Create your views here.
  16.  
  17. def index(request):
  18. print('views')
  19. return Response(request, 'index.html')
  20.  
  21. @cache_page(10) # 使用装饰器进行局部缓存,生效时间十秒
  22. def cache1(request, page):
  23. t = time.time()
  24. return render(request, 'cache.html', {'t': t})
  25.  
  26. def cache2(request):
  27. t = time.time()
  28. # pizza_done.send(sender='cache2', toppings=1, size=3)
  29. return render(request, 'cache.html', {'t': t})

Views.py

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. {{ t }}
  9. </body>
  10. </html>

cache.html

c、局部模板使用

在前端页面

  1. a. 引入TemplateTag
  2.  
  3. {% load cache %}
  4.  
  5. b. 使用缓存
  6.  
  7. {% cache 5000 缓存key %}
  8. 缓存内容
  9. {% endcache %}

  示例:

  1. def cache3(request): # 局部视图缓存
  2. print(type(request))
  3. t = time.time()
  4. from app01 import models
  5. print('before')
  6. # models.UserInfo.objects.create(name='test')
  7. print('after')
  8. # pizza_done.send(sender='cache3', toppings=123, size=456)
  9. return render(request, 'cache3.html', {'t': t})

Views.py

  1. {% load cache %}
  2. <!DOCTYPE html>
  3. <html lang="en">
  4. <head>
  5. <meta charset="UTF-8">
  6. <title>Title</title>
  7. </head>
  8. <body>
  9. {{ t }}
  10. <hr />
  11. {% cache 10 nnn %} {# 缓存十秒 #}
  12. {{ t }}
  13. {% endcache %}
  14.  
  15. </body>
  16. </html>

cache3.html

信号

Django中提供了“信号调度”,用于在框架执行操作时解耦。通俗来讲,就是一些动作发生的时候,信号允许特定的发送者去提醒一些接受者。

  Django内置信号

  1. Model signals
  2. pre_init # django的modal执行其构造方法前,自动触发
  3. post_init # django的modal执行其构造方法后,自动触发
  4. pre_save # django的modal对象保存前,自动触发
  5. post_save # django的modal对象保存后,自动触发
  6. pre_delete # django的modal对象删除前,自动触发
  7. post_delete # django的modal对象删除后,自动触发
  8. m2m_changed # django的modal中使用m2m字段操作第三张表(add,remove,clear)前后,自动触发
  9. class_prepared # 程序启动时,检测已注册的app中modal类,对于每一个类,自动触发
  10. Management signals
  11. pre_migrate # 执行migrate命令前,自动触发
  12. post_migrate # 执行migrate命令后,自动触发
  13. Request/response signals
  14. request_started # 请求到来前,自动触发
  15. request_finished # 请求结束后,自动触发
  16. got_request_exception # 请求异常后,自动触发
  17. Test signals
  18. setting_changed # 使用test测试修改配置文件时,自动触发
  19. template_rendered # 使用test测试渲染模板时,自动触发
  20. Database Wrappers
  21. connection_created # 创建数据库连接时,自动触发

对于Django内置的信号,仅需注册指定信号,当程序执行相应操作时,自动触发注册函数:

  1. from django.core.signals import request_finished
  2. from django.core.signals import request_started
  3. from django.core.signals import got_request_exception
  4.  
  5. from django.db.models.signals import class_prepared
  6. from django.db.models.signals import pre_init, post_init
  7. from django.db.models.signals import pre_save, post_save
  8. from django.db.models.signals import pre_delete, post_delete
  9. from django.db.models.signals import m2m_changed
  10. from django.db.models.signals import pre_migrate, post_migrate
  11.  
  12. from django.test.signals import setting_changed
  13. from django.test.signals import template_rendered
  14.  
  15. from django.db.backends.signals import connection_created
  16.  
  17. def callback(sender, **kwargs):
  18. print("xxoo_callback")
  19. print(sender,kwargs)
  20.  
  21. xxoo.connect(callback)
  22. # xxoo指上述导入的内容
  1. from django.core.signals import request_finished
  2. from django.dispatch import receiver
  3.  
  4. @receiver(request_finished)
  5. def my_callback(sender, **kwargs):
  6. print("Request finished!")

  自定义信号

a. 定义信号

  1. import django.dispatch
  2. pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"])

b. 注册信号

  1. def callback(sender, **kwargs):
  2. print("callback")
  3. print(sender,kwargs)
  4.  
  5. pizza_done.connect(callback)

c. 触发信号

  1. from 路径 import pizza_done
  2.  
  3. pizza_done.send(sender='seven',toppings=123, size=456)

由于内置信号的触发者已经集成到Django中,所以其会自动调用,而对于自定义信号则需要开发者在任意位置触发。

上传文件

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <form action="/upload_file/" enctype="multipart/form-data" method="POST">
  9. {% csrf_token %}
  10. <input type="file" name="fafafa" />
  11.  
  12. <input type="submit" value="提交" />
  13. </form>
  14. </body>
  15. </html>

file.html

  1. from django.shortcuts import render,HttpResponse
  2.  
  3. # Create your views here.
  4.  
  5. def upload_file(request):
  6. if request.method == "POST": # 以POST 的方式
  7. file_name = request.FILES
  8. file_obj = file_name.get("file_name_1") # 获取到封装了文件操作的对象
  9. f = open(file_obj.name, "wb")
  10. for line in file_obj.chunks(): # 循环取数据
  11. f.write(line)
  12. f.close()
  13. return HttpResponse("上传成功")
  14. else:
  15. return render(request, "upload.html")

Views.py

序列化

关于Django中的序列化主要应用在将数据库中检索的数据返回给客户端用户,特别的Ajax请求一般返回的为Json格式。

1、serializers

  1. from django.core import serializers
  2.  
  3. ret = models.BookType.objects.all()
  4.  
  5. data = serializers.serialize("json", ret)

2、json.dumps

  1. import json
  2.  
  3. #ret = models.BookType.objects.all().values('caption')
  4. ret = models.BookType.objects.all().values_list('caption')
  5.  
  6. ret=list(ret)
  7.  
  8. result = json.dumps(ret)

由于json.dumps时无法处理datetime日期,所以可以通过自定义处理器来做扩展,如:

  1. import json
  2. from datetime import date
  3. from datetime import datetime
  4.  
  5. class JsonCustomEncoder(json.JSONEncoder):
  6.  
  7. def default(self, field):
  8.  
  9. if isinstance(field, datetime):
  10. return o.strftime('%Y-%m-%d %H:%M:%S')
  11. elif isinstance(field, date):
  12. return o.strftime('%Y-%m-%d')
  13. else:
  14. return json.JSONEncoder.default(self, field)

  

更多详见:http://www.cnblogs.com/wupeiqi/articles/5246483.html

Django进阶篇(二)的更多相关文章

  1. 02:Django进阶篇

    目录:Django其他篇 01:Django基础篇 02:Django进阶篇 03:Django数据库操作--->Model 04: Form 验证用户数据 & 生成html 05:Mo ...

  2. WPF 4 DataGrid 控件(进阶篇二)

    原文:WPF 4 DataGrid 控件(进阶篇二)      上一篇<WPF 4 DataGrid 控件(进阶篇一)>中我们通过DataGridTemplateColumn 类自定义编辑 ...

  3. Django进阶篇【1】

    注:本篇是Django进阶篇章,适合人群:有Django基础,关于Django基础篇,将在下一章节中补充! 首先我们一起了解下Django整个请求生命周期: Django 请求流程,生命周期: 路由部 ...

  4. django 进阶篇

    models(模型) 创建数据库,设计表结构和字段 使用 MySQLdb 来连接数据库,并编写数据访问层代码 业务逻辑层去调用数据访问层执行数据库操作 import MySQLdb def GetLi ...

  5. python Django 进阶篇

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

  6. Python之路【第十七篇】Django进阶篇

    规范 确立规范的好处: 代码可读性高 方便代码的定位极其查找 为以后代码扩容带来便利 场景: 在多个APP的场景下,单个app的URL函数功能较多的时候,我们可以通过以下方法来解决. 把Views写成 ...

  7. django进阶篇

    原文连接:http://www.cnblogs.com/wupeiqi/articles/5246483.html Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创 ...

  8. Python学习-day20 django进阶篇

    Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接数据库,并编写数据访问层代码 业务逻辑层去调用数据访问层执行 ...

  9. Django进阶(二)

    Template 之前的好多HTML文件中都包含类似"{{ }}"."{% %}",其实他们都是模板语言,模板本质上是HTML,但是夹杂了一些变量和标签,可以方 ...

随机推荐

  1. Xamarin Android.Views.WindowManagerBadTokenException: Unable to add window -- token android.os.BinderProxy

    Android.Views.WindowManagerBadTokenException: Unable to add window -- token android.os.BinderProxy@ ...

  2. STM32中的PWM的频率和占空比的设置

    转于http://blog.csdn.net/liming0931/article/details/8491468 下面的这个是stm32的定时器逻辑图,上来有助于理解:   TIM3的ARR寄存器和 ...

  3. ABAP程序运行锁定

    转自http://www.cnblogs.com/aBaoRong/archive/2012/06/15/2550458.html ABAP 程序运行锁 1. create a Table ZRUNN ...

  4. python 使用virtualenvrapper虚拟环境管理工具

    centos 默认安装的python是2.6版本的 使用virtualenv 环境管理工具建立python虚拟环境的时候会遇到一些错误,DEPRECATION: Python 2.6 is no lo ...

  5. 【Android Studio快捷键】之代码提示

    接下来说如何设置代码自动提示,如图: 图上内容比较多,我直接按区域划分成6块区域来说吧: 区域1:这个选项是关于提示的时候如何进行匹配,即按照什么条件来进行提示内容的搜索. All:选择这个的话,意思 ...

  6. CSS3如何去除 inline block 元素之间多出的空格

    display: inline-block 属性很好的避免了元素的浮动问题,但是会有点小问题,就是 inline-block 元素间的回车会被显示为一个空格.然而,我们写代码时,都是用回车来格式化的. ...

  7. Python实例4

    4.输入某年某月某日,判断这一天是这一年的第几天? 正解: 源码:

  8. java异常知识点整理

    异常处理机制:捕获异常(try-catch-finally)和声明抛弃异常(throw); 所有的异常类都直接或者间接地继承于Throwable类: java异常分为可查异常和不可查异常两种.可查异常 ...

  9. IDEA IntelliJ常用设置以及快捷键(转)

    转载自:http://macrochen.iteye.com/blog/1035680 关于字体的设置 IDEA下使用雅黑Consolas混合字体      快捷贱, 快捷贱 , 快捷键贱    In ...

  10. JSP - 9大内置对象及其API

    内置对象:不需要预先声明就可以在脚本代码和表达式中随意使用,有以下特点 1.由JSP规范提供,不用编写者实例化 2.提供Web容器实现和管理 3.所有JSP页面均可用 4.只有在脚本元素的表达式或者代 ...