day063--装饰器

1.装饰器

装饰器:在不改变原函数的调用方式和函数,额外的增加功能
  1. 简单装饰器

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

    @timer # func1 = timer(func1)
    def func1():
    print('func1')

  2. 函数带返回值

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

  3. 原函数携带参数

    def download(func):
    def inner(args, **kwargs):
    print('下载软件')
    func(
    args, **kwargs)
    return inner

  4. 完整的装饰器的写法

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

  5. 装饰器带参数

    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
    return timer

    @outer(True) # func1 = timer(func1) inner
    def func1():
    print('func1')

  6. 多个装饰器装饰同一个函数

    def wrapper1(func):
    def inner(args, **kwargs):
    print('wrapper1 前') # 2
    ret = func(
    args, **kwargs)
    print('wrapper1 后') # 4
    return ret
    return inner

    def wrapper2(func):
    def inner(args, **kwargs):
    print('wrapper2 前') # 1
    ret = func(
    args, **kwargs)
    print('wrapper2 后') # 5
    return ret
    return inner

    @wrapper2 # func1 = wrapper2(func1) wrapper2.inner func=wrapper1.inner
    @wrapper1 # func1 = wrapper1(func1) wrapper1.inner func=func1
    def func1():
    print('func1') # 3
    return 'func1的返回值'

    print(func1()) # 6

  7. 装饰器修复技术

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

    @timer
    def func1():
    '''
    这里是func1
    :param x:
    :param y:
    :return:
    '''
    return 111

    print(func1.name) # 不修复显示inner, 修复后显示func1
    print(func1.doc) # 不修复显示none, 修复后显示func1的文档

    带参数和修复的装饰器

    from functools import wraps

    def outer(flag):
    def wrapper(func):
    @wraps(func)
    def inner(args, **kwargs):
    if flag:
    print("装饰器启动了")
    else:
    print("没有启动装饰器!!!")
    ret = func(
    args, **kwargs)
    return ret

         return inner
    
     return wrapper
    

    @outer(0)
    def hello():
    """
    :param
    :return:
    """
    print("hello")

    hello()
    print(hello.name)
    print(hello.doc)

2.视图系统

  1. CBV和FBV

  2. FBV(function based view )

  3. CBV(class based view)

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

      class AddPublisher(View):
          def get(self, request):
              pass
      
          def post(self, request):
              pass
      
    2. 使用
      url(r'^add_publisher/', views.AddPublisher.as_view()),

  4. CBV的流程

    1. views.AddPublisher.as_view() 程序加载的时候执行  ——》 view函数
      
    2. 当请求到来的时候执行view函数:
      1. self = AddPublisher()
      2. self.request = request
      3. 执行self.dispatch方法
        1. 判断请求方式是否被允许
          1. 允许时,通过反射获取到AddPublisher中定义的get或者post方法 ——》handler
          2. 不允许时,self.http_method_not_allowed ——》handler
        2. 执行handler 拿到返回结果 Httpresponse对象
  5. 给CBV加装饰器
    from django.utils.decorators import method_decorator

    1. 加载某个get/post的方法上:
      @method_decorator(timer)
      def get(self, request):
    2. 加在self.dispatch方法上(***推荐):需要自己定义dispatch方法
      @method_decorator(timer)
      def dispatch(self, request, *args, **kwargs):
      super().dispatch(request, *args, **kwargs)
    3. 加在类上:
      @method_decorator(timer, name='post')
      @method_decorator(timer, name='get')
      class AddPublisher(View):
  6. 区别

    1. 不使用method_decorator
      先收到self,第二个参数是request
      func: <function AddPublisher.dispatch at 0x00000163735176A8>
      args :<app01.views.AddPublisher object at 0x00000163735F7EF0> <WSGIRequest: GET '/add_publisher/'>
    2. 使用method_decorator
      直接绑定某个对象,不用传self, 直接收到request
      所以如果想用request,就是用此方法,直接拿第一个参数就是request
      func:<function method_decorator..dec..wrapper..bound_func at 0x0000019664B4A378>
      arsgs: <WSGIRequest: GET '/add_publisher/'>
  7. request

    print(request.method) # GET 请求反方式
    print(request.GET) # {} [] get()
    print(request.POST) # {} [] get()
    print(request.FILES)
    print(request.path_info,type(request.path_info)) # 路径信息 不包含IP和端口、参数

    print(request.get_host())
    print(request.get_full_path()) # 路径信息 + 参数

上传文件注意事项:

1. form表单的enctype = 'multipart/form-data'
   2. request.FILES中获取文件对象
     3. 使用文件对象的chunks()

        ```python
        def upload(request):
        
            if request.method == "POST":
                # print(request.body)
                file1 = request.FILES
                print(file1)
                file = file1.get('f1')
                print(file, file.name, type(file.name))
        
                with open(file.name, 'wb') as f:
                    # 将文件一点点读取,写入文件
                    for chunk in file.chunks():
                        f.write(chunk)
                return HttpResponse('上传成功!')
        
            return render(request, 'upload.html')
        ```

3.JsonResponse

from django.http import JsonResponse

def json_test(request):
    data = {'name': 'alex', 'pwd': 'alexdsb'}
    
    return JsonResponse(data)  # Content-Type: application/json
    # return HttpResponse(json.dumps(data), content_type='application/json')  # Content-Type: text/html; charset=utf-8
posted @ 2019-04-03 21:56  SuraSun  阅读(59)  评论(0)    收藏  举报