装饰器,视图系统 063

期待已久的装饰器终于闪亮登场!!!


1装饰器

定义 : 在不改变原函数的调用方式和函数 额外的增加功能

新建一个python文件 在里面写

引入:定义一个函数 要求 函数被调用执行时 打印一下执行的时间(引入事件模块)

可以定义一个时间函数  将需要执行的函数传入到时间函数里面  这样就可以了

问题  : 这样就改变了函数的调用方式 

import time
def timer(func):
    def inner():
        print(time.time())
        ret = func()   # 原来的函数 
        return ret
    return inner

def func1():
    print(func1)
    return 'func1的返回值'
a = timer(func1) # 此时返回值是inner的返回值
a()
#还是改变了调用方式
# 用下边的
func1 = timer(func1)
func1()
#这样就调用方式就不变了
#装饰器是闭包的一种应用
# 也可以这样用 这样是利用语法的情况使用装饰器
@timer # 等同于func1 = timer(func1)
def func1():
    print(func1)
    return 'func1的返回值'
func1()  

  用到了闭包

  实例代码

# 定义约会函数
# 需要先下载软件
def download(func):   # 给函数增加功能
    def inner():
        print('下载软件')
        func()
    return inner
# 使用不同工具约
#def yue(tools):
 #   print('使用{}约一约'.format(tools))
 # yue = download(yue) 
@download
def yue(tools):
    print('使用{}约一约'.format(tools))
    
# 原函数携带参数    
yue('momo')  # 现在是装饰器中的inner
yue('tantan')
yue('漂流瓶')

  完整的装饰器的写法

# 规范写法
def wrapper(func):
    def inner(*args,**kwargs):
        # 执行被装饰函数之前的操作
        ret = func(*args,**kwargs)
        # 执行被装饰函数之后进行的操作
        return ret
    return inner

# 对函数进行装饰
@wrapper
def func1():
    print('func1')
    
func1()

  装饰器的进阶内容:

# 对多个装饰器进行控制
# 定义一个开关 
# 全局定义一个
# flag = True
# if #判断 flag 
import time
flag = True
def outer(flag):
    def timer(func):
        def inner(*args,**kwargs)
            if flag:
                print(time.time())
                ret = func(*args,**kwargs)
            else:
                ret = func(*args,**kwargs)
             return ret
        return inner
    
@outer(True)
def func1():
    print('func1')  会执行装饰器
   
@outer(False)
def func2():
    print('func2')
    
func1()
func2()

  打印结果我们会发现 func2函数没有打印时间 也即对func2实现了写了装饰器但没有添加装置器的效果

  多个装饰器装饰同一个函数:

#固定用法 
def wrapper1(func1):
    def inner(*args,**kwargs):
        print('wrapper1 前')  #2
        ret = func(*args,**kwargs)
        print('wrapper1后')  #5
        return ret
    return inner
def wrapper2(func2):
    def inner(*args,**kwargs)
        print('wrapper2前')  #1
        ret = func(*args,**kwargs)
        print('wrapper2后') #4
        return ret
    return inner
@wrapper2 # func1 = wrapper2(func1)  wrapper2.inner
@wrapper1  # func1 = wrapper1(func1)  wrapper1.inner
#func = func1
def func1(): print('func1') #3 return 'func1的返回值' print(func1()) # 6

# 这样走的思路 首先 wrapper1先对func1进行装饰 装饰完之后 func1 = wrapper(func1) 即此时的
#func1实际上是wrapper1的inner函数 再进行装饰也即将wrapper1的inner函数进行装饰
#即func1 = wrapper1
的inner函数 所以最终的显示结果为 先执行wrapper2的inner函数 打印'wrapper2前'
#接着往下执行,此时的函数为wrapper1的inner函数 即跳转到wrapper1中,打印'wrapper1前',再接着执行的就
#是wrapper1里面的包裹的函数也即真正的func1 打印'func1' 接着往下执行 打印'wrapper1后'接着返回d到
'
wrapper2后' 执行完装饰器 接着就是执行自身的返回值
# 执行完就返回本身 接着再往下进行

可以用此图理解 装饰之后按顺序进行显示  每一层执行完之后就返回本身 接着继续向下进行

装饰器修复技术:

# 需求 要知道是哪个函数执行的
#print(func1(__name__))

#from functools import wraps
# 将 @wraps(func)放入到inner上边就可以
import time
from functiontools import wraps
def timer(func):
    @wraps(func)
    def inner():
        print(time.time())
        ret = func()  # 原来的函数
        return ret
    return inner
@timer # func1 = timer(func1)
def func1():
     """
    func1 xxxx
    :return:
    """
    print('func1')
    return 'func1的返回值'

@timer  # func1 = timer(func1)
def func2():
    """
    func2 xxxx
    :return:
    """
    print('func2')
    return 'func2的返回值'

print(func1.__name__)
print(func2.__name__)
print(func2.__doc__)  # 加了此行就会显示出函数2的注释 在日志中加入此项就可以辨别出到底是哪个函数执行的
显示结果为
func1
func2

    func2 xxxx
    :return:
2视图系统
  1 CBV和FBV

    FBV(function based view)

    CBV(class based view)

  我们之前写过的都是基于函数的view,就叫FBV.还可以把view 写成基于类的.

  写CBV的步骤:

    1 定义:

# 增加出版社 CBV
from django.views import View

class AddPublisher(View):
    def get(self, request):
        pass

    def post(self, request):
        pass

     2 使用:

url(r'^add_publishe/',views.AddPublisher.as_view()) #一定要有括号 才能执行

      3 CBV的流程:

      1:

views.AddPublisher.as_view()  程序加载的时候执行   view函数

       2:当请求到来的时候执行view函数:   1 self = AddPublisher()   2 self.request =       request   3:执行self.dispatch方法 : 1 判断请求方法是否被允许  允许时 通过反射获取到AddPublisher中定义的get或者post的方法 通过handler   不允许时self.http_method_not_allowed  也是通过handler拿到    2 执行handler拿到返回结果  HttpResponse对象

     4 . 给CBV加装饰器

      from django.utils.decorators import method_decorator

      1 加载某个get/post的方法上:

@method_decorator(timer)
    def get(self,request):


#2加载self.dispatch方法上 (推荐用法)
@method_decorator(timer)
    def dispatch(self,request,*args,**kwargs);

#3加在类上
@method_decorator(timer,name='post')  # 必须有name字段 指定给哪一种方式加装饰器
@method_decorator(timer,name='get')
class AddPublisher(view):          
 简例如下
class AddPublisher(View):
     #可以自己定义request的方法
    # http_method_names = ['get']
    @method_decorator(timer)
    def dispatch(self, request, *args, **kwargs):
        # 操作
        # start = time.time()
        ret = super().dispatch(request, *args, **kwargs)
        # end = time.time()
        # print('时间:{}'.format(end - start))
        # 操作
        return ret

    # @method_decorator(timer)
    def get(self, request):
        print('get')
        return render(request, 'add_publisher.html')

    # @method_decorator(timer)
    def post(self, request):

        print('post')
        err_msg = ''
        new_name = request.POST.get('new_name')
        if not new_name:
            err_msg = '不能为空'
        obj_list = models.Publisher.objects.filter(name=new_name)
        if obj_list:
            err_msg = '数据已存在'
        if new_name and not obj_list:
            ret = models.Publisher.objects.create(name=new_name)
            return redirect('/publisher_list/')
        return render(request, 'add_publisher.html', {'err_msg': err_msg, 'new_name': new_name})
    
View Code
 2 request
request.method # 判断请求方式
request.GET  # 获取url上的信息 类似于字典的东西 可以通过get() 或者[]获取
request.POST  #获取form表单上提交的POST数据
request.body # 请求体 request.POST的数据就是从body里获取的
request.FILES   #一个类似于字典的对象 包含所有上传文件信息  
    #需要注意
    #1 . form表单中需要添加 enctype
    enctype = 'multipart/form-data'
    #2 .将方法改为post 添加name属性  添加{% csrf_token %}
    method = 'post'  name=''  {% csrf_token %}
    #3 .注意设置文件对象的方法  chunks


# 上传文件
def upload(request):
    if request.method =='POST':
        file = request.FILES.get('f1')
        with open(file.name, 'wb') as f:
            for chunk in file.chunks():
                f.write(chunk)
        return HttpResponse('上传成功')
    return render(request,'upload.html')

# html页面
<form action="" method="post" enctype="multipart/form-data">
    {% csrf_token %}
    文件:<input type="file"  name="f1">
    <button>上传</button>
</form>
 JsonResponse

JsonResponse是HttpResponse的子类 专门用来生成JSON编码的响应

from django.http import JsonResponse

def json_test(request):
    data = {'name':'dsb','age':'12'}
    return JsonResponse(data)


#第二种方法 自己手动设置返回值
def json_test(request):
    data = {'name':'dsb','age':'25'}
    return HttpResponse(json.dumps(data),Content-Type='application/json')
原文地址:https://www.cnblogs.com/f-g-f/p/10064160.html