python 之 Django框架(Django框架简介、视图装饰器

系统 1311 0

12.33 Django框架简介:

MVC,全名是Model View Controller,是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller),具有耦合性低、重用性高、生命周期成本低等优点

Django框架的设计模式借鉴了MVC框架的思想,也是分成三部分,来降低各个部分之间的耦合性。

Django框架的不同之处在于它拆分的三部分为:Model(模型)、Template(模板)和View(视图),也就是MTV框架。

            
                 Model(模型):负责业务对象与数据库的对象(ORM)
   Template(模版):负责如何把页面展示给用户
   View(视图):负责业务逻辑,并在适当的时候调用Model和Template
            
          

此外,Django还有一个urls分发器,它的作用是将一个个URL的页面请求分发给不同的view处理,view再调用相应的Model和Template

12.34 View(视图)

一个视图函数(类),简称视图,是一个简单的Python 函数(类),它接受Web请求并且返回Web响应。

响应可以是一张网页的HTML内容,一个重定向,一个404错误,一个XML文档,或者一张图片。

12.341 CBV(class base view)

urls.py:

            url(r
            
              '
            
            
              ^add_class/$
            
            
              '
            
            , views.AddClass.as_view()),
          

CBV版添加班级:

            
              from
            
             django.shortcuts 
            
              import
            
            
               HttpResponse, render, redirect

            
            
              from
            
             django.views 
            
              import
            
            
               View

            
            
              from
            
             app01 
            
              import
            
            
               models

            
            
              class
            
            
               AddClass(View):
    
            
            
              def
            
            
               get(self, request):
        
            
            
              return
            
             render(request, 
            
              "
            
            
              add_class.html
            
            
              "
            
            
              )
    
            
            
              def
            
            
               post(self, request):
        class_name 
            
            = request.POST.get(
            
              "
            
            
              class_name
            
            
              "
            
            
              )
        models.Classes.objects.create(name
            
            =
            
              class_name)
        
            
            
              return
            
             redirect(
            
              "
            
            
              /class_list/
            
            
              "
            
            )
          
12.342 视图装饰器

装饰器装饰FBV:

            
              def
            
            
               wrapper(func):
    
            
            
              def
            
             inner(*args, **
            
              kwargs):
        start_time 
            
            =
            
               time.time()
        ret 
            
            = func(*args, **
            
              kwargs)
        end_time 
            
            =
            
               time.time()
        
            
            
              print
            
            (
            
              "
            
            
              used:
            
            
              "
            
            , end_time-
            
              start_time)
        
            
            
              return
            
            
               ret
    
            
            
              return
            
            
               inner
​

            
            
              #
            
            
               FBV版添加班级
            
            
              @wrapper

            
            
              def
            
            
               add_class(request):
    
            
            
              if
            
             request.method == 
            
              "
            
            
              POST
            
            
              "
            
            
              :
        class_name 
            
            = request.POST.get(
            
              "
            
            
              class_name
            
            
              "
            
            
              )
        models.Classes.objects.create(name
            
            =
            
              class_name)
        
            
            
              return
            
             redirect(
            
              "
            
            
              /class_list/
            
            
              "
            
            
              )
    
            
            
              return
            
             render(request, 
            
              "
            
            
              add_class.html
            
            
              "
            
            )
          

装饰器装饰CBV:

类中的方法与独立函数不完全相同,因此不能直接将函数装饰器应用于类中的方法 ,需要先将其转换为方法装饰器。

Django中提供了method_decorator装饰器用于将函数装饰器转换为方法装饰器

            
              #
            
            
               CBV版添加班级
            
            
              from
            
             django.views 
            
              import
            
            
               View

            
            
              from
            
             django.utils.decorators 
            
              import
            
            
               method_decorator

            
            
              def
            
            
               wrapper(func):
    
            
            
              def
            
             inner(*args, **
            
              kwargs):
        start_time 
            
            =
            
               time.time()
        ret 
            
            = func(*args, **
            
              kwargs)
        end_time 
            
            =
            
               time.time()
        
            
            
              print
            
            (
            
              "
            
            
              used:
            
            
              "
            
            , end_time-
            
              start_time)
        
            
            
              return
            
            
               ret
    
            
            
              return
            
            
               inner
​

            
            
              #
            
            
              @method_decorator(wrapper, name='post')        给post加方法装饰器
            
            
              
#
            
            
              @method_decorator(wrapper, name='dispatch')    给dispatch方法加装饰器,相当于给类下所有方法加装饰器
            
            
              class
            
            
               AddClass(View):
    
    
            
            
              #
            
            
              http_method_names = ['get', ]                  #自定义可用的请求方法
            
            
              ​
    @method_decorator(wrapper)                      
            
            
              #
            
            
              给get方法加装饰器
            
            
              def
            
            
               get(self, request):
        
            
            
              return
            
             render(request, 
            
              "
            
            
              add_class.html
            
            
              "
            
            
              )
​
    
            
            
              def
            
            
               post(self, request):
        class_name 
            
            = request.POST.get(
            
              "
            
            
              class_name
            
            
              "
            
            
              )
        models.Classes.objects.create(name
            
            =
            
              class_name)
        
            
            
              return
            
             redirect(
            
              "
            
            
              /class_list/
            
            
              "
            
            )
          

使用CBV时要注意:请求过来后会先执行dispatch()这个方法,如果需要批量对具体的请求处理方法,如get,post等做一些操作的时候,这里我们可以手动改写dispatch方法,这个dispatch方法就和在FBV上加装饰器的效果一样。

            
              class
            
            
               Login(View):
     
    
            
            
              def
            
             dispatch(self, request, *args, **
            
              kwargs):
        
            
            
              print
            
            (
            
              '
            
            
              before
            
            
              '
            
            
              )
        obj 
            
            = super(Login,self).dispatch(request, *args, **
            
              kwargs)
        
            
            
              print
            
            (
            
              '
            
            
              after
            
            
              '
            
            
              )
        
            
            
              return
            
            
               obj
 
    
            
            
              def
            
            
               get(self,request):
        
            
            
              return
            
             render(request,
            
              '
            
            
              login.html
            
            
              '
            
            
              )
 
    
            
            
              def
            
            
               post(self,request):
        
            
            
              print
            
            (request.POST.get(
            
              '
            
            
              user
            
            
              '
            
            
              ))
        
            
            
              return
            
             HttpResponse(
            
              '
            
            
              Login.post
            
            
              '
            
            )
          
12.342 request对象

当一个页面被请求时,Django就会创建一个包含本次请求原信息的HttpRequest对象,Django会将这个对象自动传递给响应的视图函数,一般视图函数约定俗成地使用 request 参数承接这个对象

path_info 返回用户访问url的路径,不包括域名和参数:/music/bands/the_beatles/  
method 请求中使用的HTTP方法的字符串表示,全大写表示:"GET"、"POST"  
GET 包含所有HTTP GET参数的类字典对象  
POST 包含所有HTTP POST参数的类字典对象  
body 请求体,byte类型 request.POST的数据就是从body里面提取到的  
get_full_path() 返回URL中的路径和参数:/music/bands/the_beatles/?print=true  
12.343 上传文件示例

如果有上传文件,html文件中的form表单一定要加 enctype="multipart/form-data"

upload_demo.html:

            
              <
            
            
              body
            
            
              >
            
            
              <
            
            
              h1
            
            
              >
            
            Django 上传文件示例
            
              
                h1
              
              
                >
              
              
                <
              
              
                form 
              
              
                action
              
              
                ="/upload/"
              
              
                 method
              
              
                ="post"
              
              
                 enctype
              
              
                ="multipart/form-data"
              
              
                >
              
              
                <
              
              
                input 
              
              
                type
              
              
                ="text"
              
              
                 name
              
              
                ="username"
              
              
                >
              
              
                <
              
              
                input 
              
              
                type
              
              
                ="file"
              
              
                 name
              
              
                ="touxiang"
              
              
                >
              
              
                <
              
              
                input 
              
              
                type
              
              
                ="submit"
              
              
                 value
              
              
                ="提交"
              
              
                >
              
              
                
                  form
                
                
                  >
                
                
                  
                    body
                  
                  
                    >
                  
                
              
            
          

如果有上传文件,views.py中应该从 request.FILES 中取上传的文件对象

服务端接收文件:views.py

            
              from
            
             django.shortcuts 
            
              import
            
            
               render, HttpResponse

            
            
              from
            
             django.http 
            
              import
            
            
               JsonResponse

            
            
              def
            
            
               upload(request):
    
            
            
              if
            
             request.method == 
            
              "
            
            
              POST
            
            
              "
            
            
              :
        
            
            
              #
            
            
              print(request.POST)                    #只能拿到字典里的文件名
            
            
              #
            
            
              print(request.FILES)                   #拿到含有文件对象的字典
            
            
        file_obj = request.FILES.get(
            
              "
            
            
              touxiang
            
            
              "
            
            )  
            
              #
            
            
              得到文件对象
            
            
              #
            
            
              print(file_obj, type(file_obj))
            
            
        file_name = file_obj.name                
            
              #
            
            
               拿到文件名
            
            
        with open(file_name, 
            
              "
            
            
              wb
            
            
              "
            
            
              ) as f:
            
            
            
              for
            
             line 
            
              in
            
             file_obj.chunks():       
            
              #
            
            
               从上传的文件对象中一点一点读取数据
            
            
                f.write(line)                   
            
              #
            
            
               写到新建的文件中
            
            
              return
            
             HttpResponse(
            
              "
            
            
              OK
            
            
              "
            
            
              )
    
            
            
              return
            
             render(request, 
            
              "
            
            
              upload_demo.html
            
            
              "
            
            )
          
12.344 Response对象

每个视图都需要实例化,填充和返回一个HttpResponse,本质上render,redirect也是返回了HttpResponse对象

HttpResponse.content :响应内容 HttpResponse.charset :响应内容的编码 HttpResponse.status_code :响应的状态码

JsonResponse对象 :JsonResponse是HttpResponse的子类,Django封装的一个专门用来返回JSON格式数据的方法

            
              from
            
             django.http.response 
            
              import
            
            
               JsonResponse

            
            
              def
            
            
               get_json_data(request):
    data 
            
            = {
            
              "
            
            
              name
            
            
              "
            
            : 
            
              "
            
            
              Egon
            
            
              "
            
            , 
            
              "
            
            
              hobby
            
            
              "
            
            : 
            
              "
            
            
              喊麦
            
            
              "
            
            
              }
    
            
            
              #
            
            
               import json
            
            
              #
            
            
               return HttpResponse(json.dumps(data),content_type='application/json') 
            
            
              #
            
            
              设置content_type,浏览器会自动反序列化json
            
            
    <-等同于->
    
            
              #
            
            
               ret = HttpResponse(json.dumps(data))
            
            
              #
            
            
               ret['Content-type'] = 'application/json'
            
            
              #
            
            
               return ret
            
            
              return
            
            
               JsonResponse(data)
​
    
            
            
              #
            
            
              return JsonResponse([1, 2, 3, 4], safe=False)
            
            
              #
            
            
              JsonResponse默认只能传递字典类型,如果要传递非字典类型需要设置safe参数
            
          

更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论