django是一个python web开发的框架。作为一个框架MVC的架构已经实现起来了。但是编码的时候你经常要进行进一步的抽象。

AOP是一种称为面向切面的开发思想,意思是将部分功能代码在运行时动态的加载到指定位置。最常见的应用是Spring中的依赖注入@Autowired。

而装饰器也可以被看成是一种AOP的实现,但是又有些许的不同,让我们来体会一下。

在我们的实例中我们将django中的views.py(其实是controller层)拆出了implement.py(实现)和decorator.py(装饰器)

1、先看我们的views.py。

这里我们只给出一个接口做为演示。

# -*- coding:utf-8 -*-
import json
import logging
import implement
import decorator
from django.views.decorators.csrf import csrf_exempt logger = logging.getLogger(__name__) @csrf_exempt
@decorator.impl_wrapper_check_time
@decorator.process_time
@decorator.cache
def alarm_month_daytotal(request):
if request.method == 'GET':
time_str = request.GET.get('time')
return implement.alarm_month_daytotal(time_str)

alarm_total接口在views.py中的函数alarm_total中并没有返回JSONResponse对象,而是直接返回了调用implement.alarm_total()的结果,看样子是implement.alarm_total()返回了JSONResponse

,我们看看是不是这样。

2、implement实现层

# -*- coding:utf-8 -*-
import json
import logging
import calendar from rediss import RedisCache
from config import redis_config, alarm_status_mapping, alarm_type_mapping, alarm_level_mapping, combine_module, alarm_module_mapping,alarm_stage_mapping, \
alarm_type_config_mapping, month_total_closed_mapping, month_total_tosolve_mapping
from datetime import datetime, timedelta
from dao import Dao as dash_dao
from exceptions import DataEmptyException
import time logger = logging.getLogger(__name__) # 按月获取分天报警情况
def alarm_month_daytotal(time_str):
time_object = datetime.strptime(time_str, '%Y-%m')
month, length = calendar.monthrange(time_object.year, time_object.month)
ret_list = [0 for i in range(length)]
items = dash_dao.get_alarms_by_month(time_str)
if not items:
raise DataEmptyException('[table] %s' % 'alarm_list_table')
for item in items:
if not item.alarm_time:
continue
ret_list[at_day(item.alarm_time) - 1] += 1
r = RedisCache(redis_config)
key_list = r.keys("dmonitor:issue:%s*" % time_str)
if not key_list:
return ret_list
for key in key_list:
content = r.get(key)
time_object = datetime.strptime(key.split(':')[2], '%Y-%m-%d')
ret_list[time_object.day - 1] = {
'y': ret_list[time_object.day - 1],
'name': content,
'marker': {
'symbol': 'url(/data_monitor/static/images/sun.png)'
}
}
return ret_list

并没有啊,implement.alarm_total()只返回了一个list对象。这是为什么呢?

原因就在那几个装饰器的封装上。

3、装饰器decorator

impl_wrapper_check_time(func):执行装饰的装饰的func方法,并且对返回进行JSONResponse封装

process_time(func):统计执行时间并打印日志

cache(func):对接口的请求加入缓存

执行顺序,装饰器装饰的顺序,从下往上我们例子里是cache->process_time->impl_wrapper_check_time那么:

1、先执行impl_wrapper_check_time的开始部分

2、然后是process_time时间的start_time记录

3、cache缓存的准备

4、被装饰的函数func

5、cache缓存的返回

6、process_time的end_time记录,并打印时间日志

7、impl_wrapper_check_time返回JSONResponse

执行顺序说明:

1、异常也是按照这个顺序一级一级的向上抛出。

2、最终由impl_wrapper_check_time处理异常,返回errno:0或者-1。

3、先执行完缓存的返回,再执行时间的统计,这样可以明显观察到缓存对处理时间性能上的提升。

import logging
import time
import json
import traceback
from rediss import RedisCache
from config import redis_config, cache_timeout, cache_switch
from exceptions import IllegalParamException
from django.http import JsonResponse
from django.http import HttpResponse logger = logging.getLogger(__name__) redis = RedisCache(redis_config)def impl_wrapper_check_time(func):
def wrapper(*args, **kwargs):
try:
if args[0].method == 'GET':
if not args[0].GET.get('time'):
raise IllegalParamException('time')
data = func(*args, **kwargs)
return JsonResponse({'errno': 0, 'msg': 'success', 'data': data})
except Exception, ex:
logger.error(traceback.format_exc())
return JsonResponse({'errno': -1, 'msg': str(ex)}) return wrapper def process_time(func):
def wrapper(*args, **kwargs):
path = args[0].get_full_path()
start_time = time.time()
data = func(*args, **kwargs)
end_time = time.time()
logger.info('path: %s, process_time: %s ms' % (path, str((end_time - start_time) * 1000)))
return data
return wrapper def cache(func):
def wrapper(*args, **kwargs):
if not cache_switch:
data = func(*args, **kwargs)
return data
path = args[0].get_full_path()
dashboard_cache_key = 'dashboard:cache:%s' % path
if redis.get(dashboard_cache_key):
logger.info('[Hit Cache] path: %s' % path)
return json.loads(redis.get(dashboard_cache_key))
data = func(*args, **kwargs)
redis.set(dashboard_cache_key, json.dumps(data))
redis.expire(dashboard_cache_key, cache_timeout)
logger.info('[Query] path: %s' % path)
return data
return wrapper

python使用装饰器@函数式化django开发的更多相关文章

  1. Python 之装饰器

    Python 的装饰器可谓是提高开发效率的一大利器.然而初学装饰器的时候感觉很难理解,因为除了 Python 之外没听说哪个语言有这种东西. 而且网上看的很多解释看似容易理解,但只能很快理解了装饰器能 ...

  2. 浅谈Django的中间件与Python的装饰器

    浅谈Django的中间件 与Python的装饰器 一.原理 1.装饰器是Python的一种语法应用,利用闭包的原理去更改一个函数的功能,即让一个函数执行之前先到另外一个函数中执行其他需求语句,在执行该 ...

  3. Python各式装饰器

    Python装饰器,分两部分,一是装饰器本身的定义,一是被装饰器对象的定义. 一.函数式装饰器:装饰器本身是一个函数. 1.装饰函数:被装饰对象是一个函数 [1]装饰器无参数: a.被装饰对象无参数: ...

  4. 详解Python的装饰器

    Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现了say_hello()和say_goodbye()两个函数. def sa ...

  5. 进阶Python:装饰器 全面详解

    进阶Python:装饰器 前言 前段时间我发了一篇讲解Python调试工具PySnooper的文章,在那篇文章开始一部分我简单的介绍了一下装饰器,文章发出之后有几位同学说"终于了解装饰器的用 ...

  6. 我终于弄懂了Python的装饰器(一)

    此系列文档: 1. 我终于弄懂了Python的装饰器(一) 2. 我终于弄懂了Python的装饰器(二) 3. 我终于弄懂了Python的装饰器(三) 4. 我终于弄懂了Python的装饰器(四) 一 ...

  7. 我终于弄懂了Python的装饰器(四)

    此系列文档: 1. 我终于弄懂了Python的装饰器(一) 2. 我终于弄懂了Python的装饰器(二) 3. 我终于弄懂了Python的装饰器(三) 4. 我终于弄懂了Python的装饰器(四) 四 ...

  8. Python札记 -- 装饰器补充

    本随笔是对Python札记 -- 装饰器的一些补充. 使用装饰器的时候,被装饰函数的一些属性会丢失,比如如下代码: #!/usr/bin/env python def deco(func): def ...

  9. python基础——装饰器

    python基础——装饰器 由于函数也是一个对象,而且函数对象可以被赋值给变量,所以,通过变量也能调用该函数. >>> def now(): ... print('2015-3-25 ...

随机推荐

  1. error: The requested URL returned error: 401 Unauthorized while accessing

    我遇到的其中一个问题. 问题描述: 在git push -u origin master是,提示“error: The requested URL returned error: 401 Unauth ...

  2. Wireshark抓包TCP三次握手数据

    抓包工具 - Wireshark(详细介绍与TCP三次握手数据分析) 功能使用的详细介绍 wireshark(官方下载网站: http://www.wireshark.org/),是用来获取网络数据封 ...

  3. 转:深入Java集合学习系列:HashSet的实现原理

    0.参考文献 深入Java集合学习系列:HashSet的实现原理 1.HashSet概述: HashSet实现Set接口,由哈希表(实际上是一个HashMap实例)支持.它不保证set 的迭代顺序:特 ...

  4. 看懂c/c++ 函数、指针、数组定义

    读懂 函数 + 指针 + 数组 c语言运算符机器优先级,看这里 结合运算符优先级,我们试着读懂函数和指针 优先级简单看 表达式提升():一级优先 函数():二级优先 数组[]:二级优先 指针定义*:三 ...

  5. 团队作业4——第一次项目冲刺(Alpha版本) Day2

    1.Day 2 站立式会议: 2.leangoo任务分截图: 3.会议记录及任务分配: 队员 今日进展 明日安排 林燕 完善逻辑架构框架,继续学习微信开发 完成4.24随笔 王李焕 初步总结微信开发的 ...

  6. 201521123062《Java程序设计》第7周学习总结

    1. 本周学习总结 2. 书面作业 1.ArrayList代码分析 1.1 解释ArrayList的contains源代码 源代码如下: public boolean contains(Object ...

  7. 201521123027 《JAVA程序设计》第五周学习总结

    1.本周学习总结 1.1 尝试使用思维导图总结有关多态与接口的知识点. 1.2 可选:使用常规方法总结其他上课内容 Comparable接口与Comparator接口的区别: Markdown的其他用 ...

  8. 201521123096《Java程序设计》第四周学习总结

    1. 本周学习总结 1.1 尝试使用思维导图总结有关继承的知识点. 1.2 使用常规方法总结其他上课内容. 继承能够动态绑定,运行时能够自动的选择调用方法,十分方便. 2. 书面作业 (1)注释的应用 ...

  9. 201521123013 《Java程序设计》第1周学习总结

    1. 本章学习总结 1.Java是面向对象的编程语言,它在通过jvm和jre将其转成本地机器代码,达到一次撰写,到处运行的效益,实现跨平台运行,代码开源,使用范围广. 2.了解jdk.jre.jvm的 ...

  10. 201521123065《java程序设计》第9周学习总结

    1. 本周学习总结 2. 书面作业 本次PTA作业题集异常 题目5-1 1.1 截图你的提交结果(出现学号) 1.2 自己以前编写的代码中经常出现什么异常.需要捕获吗(为什么)?应如何避免? 出现的异 ...