zoukankan      html  css  js  c++  java
  • Django---CBV和FBV的使用,CBV的流程,给视图加装饰器,Request对象方法,属性和Response对象,form表单的上传

    Django---CBV和FBV的使用,CBV的流程,给视图加装饰器,Request请求对象方法,属性和Response响应对象,form表单的上传

    一丶CBV和FBV

          在Django中存在存在两种url和视图对应的形式:类和函数

    CBV:类视图

    ##### class based view 基于类
    	### 出版社添加 urls.py中填写url和类的对应关系.   
        	#PublishAdd是类,要执行as_view()方法
         url('^publish_add',views.PublishAdd.as_view()), # CBV
    
    	### 添加出版社,在app下的views.py写代码
    class PublishAdd(View):
    
        def get(self, request): 	# 执行get请求 , request手动传参
    			
            return render(request, 'publish_add.html')  
    
        def post(self, request):	# 执行post请求
            pname = request.POST.get('pname')
            paddr = request.POST.get('paddr')
    
            if not pname:
                error = '内容不允许为空'
            elif models.Publish.objects.filter(pname=pname):
                error = '出版社已存在'
            else:
                # 往数据库中插入数据
                models.Publish.objects.create(pname=pname, paddr=paddr)
                return redirect(to='/publish_list/')
    
            res = {'error': error, 'pname': pname, 'paddr': paddr}
            return render(request, 'publish_add.html', res)    	
    

    FBV:函数视图

    ## function based view 基于函数
    	#出版社添加
        url('^publish_add',views.publish_add), # FBV	
        
        
        ### publish_add 函数
    def publish_add(request):
        error, pname, paddr = '', '', ''
    
        if request.method == 'POST':	# 判断请求的方式是不是post
            pname = request.POST.get('pname')
            paddr = request.POST.get('paddr')
    
            if not pname:
                error = '内容不允许为空'
            elif models.Publish.objects.filter(pname=pname):
                error = '出版社已存在'
            else:
                # 往数据库中查数据
                models.Publish.objects.create(pname=pname, paddr=paddr)
                return redirect(to='/publish_list/')
        res = {'error': error, 'pname': pname, 'paddr': paddr}
        return render(request, 'publish_add.html', res)
    
    

    二丶CBV的运行流程

    1. 项目启动时,运行urls.py。
    
       url(r'^publisher_add/',views.AddPublisher.as_view() ),
       AddPublisher.as_view() 执行  ——》	执行当前类的as_view方法,如果没有当前类没有,就执行父类的View函数.
    
    2. 请求到来时,实行view函数:
    
       1. 实例化AddPublisher  ——》  self 
    
       2. self.request = request  
    
       3. 执行View中self.dispatch(request, *args, **kwargs)
    
          1. 判断请求方式是否被允许
    
             1. 允许
    
                通过反射获取请求方式对应的方法   ——》 handler
    
             2. 不允许
    
                self.http_method_not_allowed  ——》 handler
    
          2. 执行handler 获取到响应
    
    ### 源码:
    ### view 函数
    def view(request, *args, **kwargs):  # 执行view函数
                self = cls(**initkwargs)	# 实例化一个当前类对象,cls指的是当前类名.加()实例化对象
                if hasattr(self, 'get') and not hasattr(self, 'head'):
                    self.head = self.get	# 给对象封装属性
                self.request = request		
                self.args = args
                self.kwargs = kwargs
                return self.dispatch(request, *args, **kwargs)	#### 重点:执行调遣函数,确认是执行哪一个方法.
            view.view_class = cls
            view.view_initkwargs = initkwargs
    
            # take name and docstring from class
            update_wrapper(view, cls, updated=())
    
            # and possible attributes set by decorators
            # like csrf_exempt from dispatch
            update_wrapper(view, cls.dispatch, assigned=())
            return view			# 返回一个view函数执行的结果
            
            
            
    ### despatch函数        
    def dispatch(self, request, *args, **kwargs): 	
        	# 判断请求是否被允许
            if request.method.lower() in self.http_method_names:
                # 通过反射去执行具体的请求方法对应的请求函数.
                handler = getattr(self, request.method.lo 
                handler = self.http_method_not_allowed
            return handler(request, *args, **kwargs)	# 把结果交给handler处理 ,handler是执行的是http_method_not_allowed方法
    

    三丶给视图加装饰器

    CBV加装饰器

    PS:#  在get方法上也可以直接加上装饰器.也能实现额外的功能,但是不推荐使用.最好是使用method_decorator()进行'加工'装饰
        
    from django.utils.decorators import method_decorator  # 给方法加上装饰器
    
    ### 计时间装饰器
    def timmer(func):
        def inner(*args, **kwargs):
            # print('查看是方法还是函数:',func)
            # print('查看参数的类型:',args,type(args))
            # print(kwargs)
            start_time = time.time()
            ret = func(*args, **kwargs)
            print(f'当前函数运行时间:{time.time() - start_time}')
            return ret
    
        return inner
    
    
    @method_decorator(timmer, name='dispatch')  # 在类上指定具体的某个方法加上装饰器
    class PublishAdd(View):
        # @timmer # 这种方式也可以实现功能,但是传递的参数不一样,不推荐使用.  参数回到计时装饰器查看
        # 函数 : 这是一个函数  <function PublishAdd.dispatch at 0x000001F6B675CEA0>
        # 参数 : 不能直接获取WSGIRequest对象 (<app01.views.PublishAdd object at 0x000001F6B6898B38>, <WSGIRequest: GET '/publish_add/'>)
    
        # @method_decorator(timmer)  # 给所有的请求方法都加上了装饰器
        # 绑定方法:  <function method_decorator.<locals>._dec.<locals>._wrapper.<locals>.bound_func at 0x0000019DB9AE2D08>
        # 参数: (<WSGIRequest: GET '/publish_add/'>,) <class 'tuple'>
        def dispatch(self, request, *args, **kwargs):
            ret = super(PublishAdd, self).dispatch(request, *args, **kwargs)
            return ret
    
        def get(self, request):
    
            return render(request, 'publish_add.html')
    
        def post(self, request):
            pname = request.POST.get('pname')
            paddr = request.POST.get('paddr')
    
            if not pname:
                error = '内容不允许为空'
            elif models.Publish.objects.filter(pname=pname):
                error = '出版社已存在'
            else:
                # 往数据库中插入数据
                models.Publish.objects.create(pname=pname, paddr=paddr)
                return redirect(to='/publish_list/')
    
            res = {'error': error, 'pname': pname, 'paddr': paddr}
            return render(request, 'publish_add.html', res)
    
    

    FBV加装饰器

    # 由于是函数可以直接加上装饰器
    ### 计时间装饰器
    def timmer(func):
        def inner(*args, **kwargs):
            # print('查看是方法还是函数:',func)
            # print('查看参数的类型:',args,type(args))
            # print(kwargs)
            start_time = time.time()
            ret = func(*args, **kwargs)
            print(f'当前函数运行时间:{time.time() - start_time}')
            return ret
    
        return inner
    
    @timmer
    def publish_add(request):
        error, pname, paddr = '', '', ''
    
        if request.method == 'POST':	# 判断请求的方式是不是post
            pname = request.POST.get('pname')
            paddr = request.POST.get('paddr')
    
            if not pname:
                error = '内容不允许为空'
            elif models.Publish.objects.filter(pname=pname):
                error = '出版社已存在'
            else:
                # 往数据库中查数据
                models.Publish.objects.create(pname=pname, paddr=paddr)
                return redirect(to='/publish_list/')
        res = {'error': error, 'pname': pname, 'paddr': paddr}
        return render(request, 'publish_add.html', res)
    
    

    四丶Request请求 -- 属性和方法

    ret2 = request.method		# 获得请求方式
    ret3 = request.GET			# GET请求方式,url上携带的参数
    ret4 = request.POST			# POST请求方式,post请求提交的参数
    ret5 = request.path_info	#路径信息 (不包含IP和端口 也不包含查询参数)
    ret6 = request.body			# 请求体的信息
    ret7 = request.COOKIES		# cookie信息
    ret8 = request.session		# session信息
    ret9 = request.FILES		# 获得上传文件信息
    ret10 = request.META		# 获得所有的头信息
    ret11 = request.is_ajax()
    ret12 = request.get_full_path()
    

    五丶form表单上传文件

    ###input框的类型为file ,需要在 form表单设置method提交方式 'post'  和 enctype='multipart/form-data'
    
    <form class="form-inline" action="" method="post" enctype="multipart/form-data">
        <div class="form-group">
            <label for="exampleInputName2">文件上传</label>
            <input type="file" class="form-control" id="" name="file-upload" multiple>
        </div>
        <button type="submit" class="btn btn-default">上传</button>
    </form>
    
    ## 上传文件的后端代码
    def post(self,request):
            file_data=request.FILES.get('file-upload') # 使用FILES获得上传文件
            print(file_data,type(file_data))	# 打印类型
            upload_file_dirs=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
            print(upload_file_dirs)
            with open(os.path.join(upload_file_dirs,'upload',file_data.name),'wb') as f:
                for line in file_data.chunks():
                    f.write(line)
            return redirect(to='/index_test/')
    

    六丶Response响应

    # HttpResponse 返回字符串
    # render 返回一个页面   ,基于HttpResponse
    # redirect 重定向 		,基于HttpResponse
    # JsonResponse  返回json格式的数据 ,基于HttpResponse
    
    ### 最终都返回的是HttpResponse的字符串
    

          JsonResponse的使用

    from django.http.response import JsonResponse # 导入模块
    
    def json_response(request):
        data={'name':'abc','age':18}  # 字典类型的数据,默认支持
        data2=['1','2','3']    		  # 默认不支持列表或其他类型的数据.需要设置一个条件,safe=False
        							# 如:JsonResponse(data2,safe=False)
        return  JsonResponse(data)
    
    
  • 相关阅读:
    从零开始学 Web 之 DOM(七)事件冒泡
    从零开始学 Web 之 DOM(六)为元素绑定与解绑事件
    从零开始学 Web 之 DOM(五)元素的创建
    从零开始学 Web 之 DOM(四)节点
    从零开始学 Web 之 DOM(三)innerText与innerHTML、自定义属性
    从零开始学 Web 之 DOM(二)对样式的操作,获取元素的方式
    从零开始学 Web 之 DOM(一)DOM的概念,对标签操作
    @RequestParam和@GetMapping
    组件(一)
    Vue(一)
  • 原文地址:https://www.cnblogs.com/dengz/p/11439401.html
Copyright © 2011-2022 走看看