一,装饰器的概念与使用
文章见https://www.jb51.net/article/153214.htm,本文不做过多赘述
二,装饰器实现面向切面编程的具体方法
众所周知,装饰器是python的语法糖,对于简化代码书写,提高代码复用具有很大意义,装饰器常用于打印日志,计时器,登录检查,其中django的login_required便是对页面访问进行约束,只有登陆才能访问页面,装饰器的作用包括但不仅限于此。
举个例子:
当前楼主的需求是:
假设django视图中存在耗时操作,但是遇到耗时操作,客户端便存在等待时间,这极大的影响了客户体验,俗话说用户就是上帝,我们需要制造一些假数据返回前台,告诉前台,后台数据在取数据这块由于不要可抗力造成卡顿延误。
菜鸟级解决方案:
对于每一个视图,增加超时时间,超时即返回默认空json字符串给前台
import json
import time
import signal
from django.http import HttpResponse
def view1():
try:
signal.signal(signal.SIGALRM, myHandler)
signal.alarm(1) # 设置超时时间一秒
response = urllib2.urlopen("某一耗时网站A")
result_str = json.loads(response.read())
signal.alarm(0)
return HttpResponse(result_str, content_type="application/json")
except:
return HttpResponse({}, content_type="application/json")
def view2():
try:
signal.signal(signal.SIGALRM, myHandler)
signal.alarm(1) # 设置超时时间一秒
response = urllib2.urlopen("某一耗时网站B")
result_str = json.loads(response.read())
signal.alarm(0)
return HttpResponse(result_str, content_type="application/json")
except:
return HttpResponse({}, content_type="application/json")
def view3():
try:
signal.signal(signal.SIGALRM, myHandler)
signal.alarm(1) # 设置超时时间一秒
response = urllib2.urlopen("某一耗时网站C")
result_str = json.loads(response.read())
signal.alarm(0)
return HttpResponse(result_str, content_type="application/json")
except:
return HttpResponse({}, content_type="application/json")
def view4():
try:
signal.signal(signal.SIGALRM, myHandler)
signal.alarm(1) # 设置超时时间一秒
response = urllib2.urlopen("某一耗时网站D")
result_str = json.loads(response.read())
signal.alarm(0)
return HttpResponse(result_str, content_type="application/json")
except:
return HttpResponse({}, content_type="application/json")
普通人解决方案,显然利用第二种方案,使用装饰器后不仅将代码模块化,而且更能清晰明了的表达代码作用
def TimeOut(func):
def function(*args, **kwargs):
try:
signal.signal(signal.SIGALRM, myHandler)
signal.alarm(1)
stime = time.time()
print("程序开始运行")
func(*args, **kwargs)
print("程序结束运行")
print(time.time() - stime)
signal.alarm(0)
except:
return HttpResponse({}, content_type="application/json")
return function
@TimeOut
def view1():
response = urllib2.urlopen("某一耗时网站A")
result_str = json.loads(response.read())
signal.alarm(0)
return HttpResponse(result_str, content_type="application/json")
@TimeOut
def view2():
response = urllib2.urlopen("某一耗时网站B")
result_str = json.loads(response.read())
return HttpResponse(result_str, content_type="application/json")
@TimeOut
def view3():
response = urllib2.urlopen("某一耗时网站C")
result_str = json.loads(response.read())
return HttpResponse(result_str, content_type="application/json")
@TimeOut
def view4():
response = urllib2.urlopen("某一耗时网站D")
result_str = json.loads(response.read())
return HttpResponse(result_str, content_type="application/json")
大神解决方案:对于每个视图函数定制化的返回需要的结果
def TimeOut(view):
def wrap(func):
def function(*args, **kwargs):
try:
signal.signal(signal.SIGALRM, myHandler)
signal.alarm(1)
stime = time.time()
print("程序开始运行")
func(*args, **kwargs)
print("程序结束运行")
print(time.time() - stime)
signal.alarm(0)
except:
if view == "view1":
dict = "view1需要返回的结果"
if view == "view2":
dict = "view2需要返回的结果"
if view == "view3":
dict = "view3需要返回的结果"
if view == "view4":
dict = "view4需要返回的结果"
return HttpResponse(dict, content_type="application/json")
return function
return wrap
@TimeOut("view1")
def view1():
response = urllib2.urlopen("某一耗时网站A")
result_str = json.loads(response.read())
signal.alarm(0)
return HttpResponse(result_str, content_type="application/json")
@TimeOut("view2")
def view2():
response = urllib2.urlopen("某一耗时网站B")
result_str = json.loads(response.read())
return HttpResponse(result_str, content_type="application/json")
@TimeOut("view3")
def view3():
response = urllib2.urlopen("某一耗时网站C")
result_str = json.loads(response.read())
return HttpResponse(result_str, content_type="application/json")
@TimeOut("view4")
def view4():
response = urllib2.urlopen("某一耗时网站D")
result_str = json.loads(response.read())
return HttpResponse(result_str, content_type="application/json")