gpt4 book ai didi

Django之视图层

转载 作者:我是一只小鸟 更新时间:2022-12-15 06:31:15 32 4
gpt4 key购买 nike

视图函数

视图层介绍

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

响应可以是一个 HTML 页面、一个 404 错误页面、重定向页面、XML 文档、或者一张图片… 。

每个视图函数都负责返回一个 HttpResponse 对象,对象中包含生成的响应.

代码写在哪里都可以,只要在 Python 目录下面,一般约定是将视图放置在项目或应用程序目录中的名为 views.py 的文件中.

视图层作用

  • 作用:主要存放业务核心逻辑代码

视图层,熟练掌握两个对象即可: 请求对象(request) 和 响应对象(HttpResponse) 。

视图层之必会三板斧

django视图函数必须要返回一个HttpResponse对象 否则报错:The view app01.views.func1 didn't return an HttpResponse object. It returned None instead.提示你没有返回一个Httpresponse对象而是返回了一个None.

  。

 为什么必须要返回这个对象呢?我们 Ctrl + 鼠标点击分别查看三者的源码来查探究竟.

HttpResponse源码

                          
                            class
                          
                          
                             HttpResponse(HttpResponseBase):
    
                          
                          
                            """
                          
                          
                            
    An HTTP response class with a string as content.

    This content that can be read, appended to or replaced.
    
                          
                          
                            """
                          
                          
                            
    streaming 
                          
                          =
                          
                             False

    
                          
                          
                            def
                          
                          
                            __init__
                          
                          (self, content=b
                          
                            ''
                          
                          , *args, **
                          
                            kwargs):
        super(HttpResponse, self).
                          
                          
                            __init__
                          
                          (*args, **
                          
                            kwargs)
        
                          
                          
                            #
                          
                          
                             Content is a bytestring. See the `content` property methods.
                          
                          
        self.content = content 
                        

由此可得,HttpResponse()就是对象,括号内直接跟一个具体的字符串作为响应体,示例如下 。

                          
                            HttpResponse(): 返回文本,参数为字符串,字符串中写文本内容。如果参数为字符串里含有 html 标签,也可以渲染。
 
                          
                          
                            def
                          
                          
                             runoob(request):
    
                          
                          
                            #
                          
                          
                             return HttpResponse("百度首页")
                          
                          
                            return
                          
                           HttpResponse(
                          
                            "
                          
                          
                            <a href='https://www.baidu.com/'>百度首页</a>
                          
                          
                            "
                          
                          )
                        

render源码

  • 底层返回的也是 HttpResponse 对象
                          
                            def
                          
                           render(request, template_name, context=None, content_type=None, status=None, using=
                          
                            None):
        
                          
                          
                            """
                          
                          
                            
        Returns a HttpResponse whose content is filled with the result of calling
        django.template.loader.render_to_string() with the passed arguments.
        
                          
                          
                            """
                          
                          
                            
        content 
                          
                          = loader.render_to_string(template_name, context, request, using=
                          
                            using)
        
                          
                          
                            return
                          
                          
                             HttpResponse(content, content_type, status)
  

                          
                          
                            '''
render(request, template_name[, context])`  `结合一个给定的模板和一个给定的上下文字典,并返回一个渲染后的 HttpResponse 对象。
参数:
     request: 用于生成响应的请求对象。

     template_name:要使用的模板的完整名称,可选的参数

     context:添加到模板上下文的一个字典。默认是一个空字典。如果字典中的某个值是可调用的,视图将在渲染模板之前调用它。

render方法就是将一个模板页面中的模板语法进行渲染,最终渲染成一个html页面作为响应体。
'''
                          
                        

redirect源码

  • redirect内部是继承了HttpRespone类

  。

  。

  。

  。

小结:

响应对象 。

  • 响应对象主要有三种形式:HttpResponse(),render(),redirect()
  • HttpResponse():返回文本,参数为字符串,字符串中写文本内容。
  • render():返回文本,第一个参数为request,第二个参数为 字符串(或html页面文件),第三个参数为字典(可选参数,向页面传递的参数:键为页面参数名,值为views参数名)
  • redirect():重定向,跳转到新页面。参数为字符串,字符串中填写页面路径。一般用于form提交数据后跳转到新页面

三板斧本质

  • ender 和 redirect 是在 HttpResponse 的基础上进行了封装:
  • render:底层返回的也是 HttpResponse 对象
  • redirect:底层继承的是 HttpResponse 对象

JsonResponse对象

1.作用

全称:JSON的全称是"JavaScript Object Notation", 意思是JavaScript对象表示法 。

作用:前后端交互一般使用的是json实现数据的跨域传输 。

2.向前端返回一个json格式字符串的两种方式

方法一:直接自己序列化 。

                          
                            import
                          
                          
                             json


                          
                          
                            def
                          
                          
                             index_func(request):
    user_dict 
                          
                          = {
                          
                            '
                          
                          
                            name
                          
                          
                            '
                          
                          :
                          
                            '
                          
                          
                            alex
                          
                          
                            '
                          
                          ,
                          
                            '
                          
                          
                            age
                          
                          
                            '
                          
                          :
                          
                            '
                          
                          
                            18
                          
                          
                            '
                          
                          ,
                          
                            '
                          
                          
                            性别
                          
                          
                            '
                          
                          :
                          
                            '
                          
                          
                          
                            '
                          
                          
                            }
    user_json 
                          
                          = json.dumps(user_dict,ensure_ascii=
                          
                            False)
    
                          
                          
                            return
                          
                          
                             HttpResponse(user_json)


                          
                          
                            #
                          
                          
                             添加ensure_ascii=False 参数是为了让中文保持正常显示, 不然会转换成uncode格式
                          
                        

 方法二:使用JsonResponse对象 。

                          
                            from
                          
                           django.http 
                          
                            import
                          
                          
                             JsonResponse


                          
                          
                            def
                          
                          
                             index_func(request):
    user_dict 
                          
                          = {
                          
                            '
                          
                          
                            name
                          
                          
                            '
                          
                          :
                          
                            '
                          
                          
                            alex
                          
                          
                            '
                          
                          ,
                          
                            '
                          
                          
                            age
                          
                          
                            '
                          
                          :
                          
                            '
                          
                          
                            18
                          
                          
                            '
                          
                          ,
                          
                            '
                          
                          
                            性别
                          
                          
                            '
                          
                          :
                          
                            '
                          
                          
                          
                            '
                          
                          
                            }
    
                          
                          
                            return
                          
                           JsonResponse(user_dict)
                        

  。

  。

问题:bJsonResponse 对象没有  ensure_ascii  参数来保证中文正常显示吗?

首先,我们来查看源码.

  。

 由源码可知, json_dumps_params 是一个字典,接下来我们为 json_dumps_params 传入参数.

                          
                            from
                          
                           django.http 
                          
                            import
                          
                          
                             JsonResponse


                          
                          
                            def
                          
                          
                             index_func(request):
    user_dict 
                          
                          = {
                          
                            '
                          
                          
                            name
                          
                          
                            '
                          
                          :
                          
                            '
                          
                          
                            alex
                          
                          
                            '
                          
                          ,
                          
                            '
                          
                          
                            age
                          
                          
                            '
                          
                          :
                          
                            '
                          
                          
                            18
                          
                          
                            '
                          
                          ,
                          
                            '
                          
                          
                            性别
                          
                          
                            '
                          
                          :
                          
                            '
                          
                          
                          
                            '
                          
                          
                            }
    
                          
                          
                            return
                          
                           JsonResponse(user_dict,
                          
                            json_dumps_params={'ensure_ascii':False}
                          
                          )
                        

ps:以后写代码很多时候可能需要参考源码及所学知识扩展功能 。

                          
                            class
                          
                          
                             JsonResponse():
    
                          
                          
                            def
                          
                          
                            __init__
                          
                          (self,data,json_dumps_params=
                          
                            None):
        json.dumps(data,
                          
                          **json_dumps_params)
                        

JsonResponse主要序列化字典,针对非字典的其他可以被序列化的数据需要修改safe参数为False 。

                          
                            from
                          
                           django.http 
                          
                            import
                          
                          
                             JsonResponse


                          
                          
                            def
                          
                          
                             index_func(request):
    user_list 
                          
                          = [11,22,33,44,55
                          
                            ]
    
                          
                          
                            return
                          
                           JsonResponse(user_list,json_dumps_params={
                          
                            '
                          
                          
                            ensure_ascii
                          
                          
                            '
                          
                          :False})
                        

  。

提示为了让非字典对象能够被序列化,设置safe参数为false.

我代码没有写这个啊,这是哪来的呢?

凭空捏造??且看 JsonResonse 源代码 。

 加入  safe=False  参数, 让其允许非 dict 对象被序列化 。

                          
                            from
                          
                           django.http 
                          
                            import
                          
                          
                             JsonResponse


                          
                          
                            def
                          
                          
                             index_func(request):
    user_list 
                          
                          = [11,22,33,44,55
                          
                            ]
    
                          
                          
                            return
                          
                           JsonResponse(user_list,safe=False,json_dumps_params={
                          
                            '
                          
                          
                            ensure_ascii
                          
                          
                            '
                          
                          :False})
                        

ps: JsonResponse 返回的也是 HttpResponse 对象 。

                          
                            class
                          
                           JsonResponse(HttpResponse):  
                          
                            #
                          
                          
                             继承了HttpResponse
                          
                          
    ...
                        

视图层之request对象获取文件

                          request.FILES    
                          
                            #
                          
                          
                             获取文件对象
                          
                        

1.form表单上传文件注意事项

  1. method 必须是 post
  2. enctype 参数修改为 multipart/form-data

2.实现代码

index_Page.html文件 。

                          
                            <!
                          
                          
                            DOCTYPE html
                          
                          
                            >
                          
                          
                            <
                          
                          
                            html 
                          
                          
                            lang
                          
                          
                            ="en"
                          
                          
                            >
                          
                          
                            <
                          
                          
                            head
                          
                          
                            >
                          
                          
                            <
                          
                          
                            meta 
                          
                          
                            charset
                          
                          
                            ="UTF-8"
                          
                          
                            >
                          
                          
                            <
                          
                          
                            title
                          
                          
                            >
                          
                          Title
                          
                            </
                          
                          
                            title
                          
                          
                            >
                          
                          
                            <
                          
                          
                            script 
                          
                          
                            src
                          
                          
                            ="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"
                          
                          
                            ></
                          
                          
                            script
                          
                          
                            >
                          
                          
                            </
                          
                          
                            head
                          
                          
                            >
                          
                          
                            <
                          
                          
                            body
                          
                          
                            >
                          
                          
                            <
                          
                          
                            form 
                          
                          
                            action
                          
                          
                            =""
                          
                          
                             method
                          
                          
                            ="post"
                          
                          
                             enctype 
                             =  "multipart/form-data"  
                          
                          
                            >
                          
                          
                            <
                          
                          
                            p
                          
                          
                            >
                          
                          
                            file:
            
                          
                          
                            <
                          
                          
                            input 
                          
                          
                            type
                          
                          
                            ="file"
                          
                          
                             name
                          
                          
                            ="file"
                          
                          
                             multiple
                          
                          
                            ="multiple"
                          
                          
                            >
                          
                          
                            </
                          
                          
                            p
                          
                          
                            >
                          
                          
                            <
                          
                          
                            input 
                          
                          
                            type
                          
                          
                            ="submit"
                          
                          
                             value
                          
                          
                            ="提交"
                          
                          
                            >
                          
                          
                            </
                          
                          
                            form
                          
                          
                            >
                          
                          
                            </
                          
                          
                            body
                          
                          
                            >
                          
                          
                            </
                          
                          
                            html
                          
                          
                            >
                          
                        

views.py文件 。

                          
                            from
                          
                           django.shortcuts 
                          
                            import
                          
                          
                             render


                          
                          
                            def
                          
                          
                             index_func(request):
    
                          
                          
                            if
                          
                           request.method == 
                          
                            '
                          
                          
                            POST
                          
                          
                            '
                          
                          
                            :
        
                          
                          
                            #
                          
                          
                             获取文件数据 
                          
                          
                            print
                          
                          (request.FILES)    
                          
                            # <MultiValueDict: {'file': [<InMemoryUploadedFile: 试卷.pdf (application/pdf)>]}>
                          
                          
                            #
                          
                          
                             获取文件数据对象   
                          
                          
        file_obj = request.FILES.get(
                          
                            '
                          
                          
                            file
                          
                          
                            '
                          
                          
                            )
        
                          
                          
                            print
                          
                          (file_obj,type(file_obj))      
                          
                            #
                          
                          
                             试卷.pdf   <class 'django.core.files.uploadedfile.InMemoryUploadedFile'>
                          
                          
                            #
                          
                          
                             获取文件对象字符串名
                          
                          
                            print
                          
                          (file_obj.name,type(file_obj.name))    
                          
                            #
                          
                          
                             试卷.pdf   <class 'str'>
                          
                          
                                    
        with open(r
                          
                          
                            '
                          
                          
                            %s
                          
                          
                            '
                          
                           % file_obj.name, 
                          
                            '
                          
                          
                            wb
                          
                          
                            '
                          
                          
                            ) as f:
            
                          
                          
                            for
                          
                           line 
                          
                            in
                          
                          
                             file_obj:
                f.write(line)

    
                          
                          
                            return
                          
                           render(request,
                          
                            '
                          
                          
                            indexPage.html
                          
                          
                            '
                          
                          )         
                        

FBV与CBV

FBV基于函数的视图(Function base view)

  • 之前我们在视图层都用的是基于函数的视图,使用函数来处理不同的请求。

基于视图的函数我们学习Django的时候就就已经在使用了,示例如下:

urls.py文件 。

                          urlpatterns =
                          
                             [
    path(
                          
                          
                            "
                          
                          
                            login/
                          
                          
                            "
                          
                          
                            , views.login),
]
                          
                        

views.py文件 。

                          
                            from
                          
                           django.shortcuts 
                          
                            import
                          
                          
                             render,HttpResponse


                          
                          
                            def
                          
                          
                             login(request):
    
                          
                          
                            if
                          
                           request.method == 
                          
                            "
                          
                          
                            GET
                          
                          
                            "
                          
                          
                            :
        
                          
                          
                            return
                          
                           HttpResponse(
                          
                            "
                          
                          
                            GET 方法
                          
                          
                            "
                          
                          
                            )
    
                          
                          
                            if
                          
                           request.method == 
                          
                            "
                          
                          
                            POST
                          
                          
                            "
                          
                          
                            :
        user 
                          
                          = request.POST.get(
                          
                            "
                          
                          
                            user
                          
                          
                            "
                          
                          
                            )
        pwd 
                          
                          = request.POST.get(
                          
                            "
                          
                          
                            pwd
                          
                          
                            "
                          
                          
                            )
        
                          
                          
                            if
                          
                           user == 
                          
                            "
                          
                          
                            shawn
                          
                          
                            "
                          
                          
                            and
                          
                           pwd == 
                          
                            "
                          
                          
                            123456
                          
                          
                            "
                          
                          
                            :
            
                          
                          
                            return
                          
                           HttpResponse(
                          
                            "
                          
                          
                            POST 方法
                          
                          
                            "
                          
                          
                            )
        
                          
                          
                            else
                          
                          
                            :
            
                          
                          
                            return
                          
                           HttpResponse(
                          
                            "
                          
                          
                            POST 方法1
                          
                          
                            "
                          
                          )
                        

如果我们在浏览器中直接访问 http://127.0.0.1:8000/login/ ,输出结果为: GET 方法 。

CBV基于类的视图(Class base view)

基本介绍

  • 采用采用面向对象的方法写视图文件。
  • 使用类来处理视图层的请求

基本使用

视图层views.py文件 。

                          
                            from
                          
                           django 
                          
                            import
                          
                          
                             views


                          
                          
                            class
                          
                          
                             MyloginView(views.View):
    
                          
                          
                            def
                          
                          
                             get(self, request):
        
                          
                          
                            return
                          
                           HttpResponse(
                          
                            '
                          
                          
                            from CBV get function
                          
                          
                            '
                          
                          
                            )
    
                          
                          
                            def
                          
                          
                             post(self,request):
        
                          
                          
                            return
                          
                           HttpResponse(
                          
                            '
                          
                          
                            from CBV post function
                          
                          
                            '
                          
                          )
                        

路由层urls.py文件 。

                          
                            from
                          
                           django.contrib 
                          
                            import
                          
                          
                             admin

                          
                          
                            from
                          
                           django.urls 
                          
                            import
                          
                          
                             path

                          
                          
                            from
                          
                           app01 
                          
                            import
                          
                          
                             views

urlpatterns 
                          
                          =
                          
                             [
    path(
                          
                          
                            '
                          
                          
                            login/
                          
                          
                            '
                          
                          
                            ,views.MyloginView.
                             as_view() 
                            )
]
                          
                        

CBV会自动根据请求方法的不同自动匹配对应的方法并执行 。

CBV源码剖析(重要)

1.储备知识

  • 面向对象属性查找顺序
  • 类方法特性
  • 反射中getattr( ) 提前了解一下

2.突破口

                          path(
                          
                            '
                          
                          
                            login/
                          
                          
                            '
                          
                          , views.MyLoginView.as_view())    
                          
                            #
                          
                          
                             as_view() 是什么东西
                          
                        

我们 Ctrl + 点击查看其源码 。

发现它是一个类方法, 查看其整体结构(只看框起来的即可, 其他的不用管), 该方法内部有一个  view  方法, 并且返回值是  view  的内存地址, 类似于闭包函数 。

  。

 于是我们就可以得到一些初步结果 。

                          path(
                          
                            '
                          
                          
                            login/
                          
                          
                            '
                          
                          , views.MyLoginView.as_view())    
                          
                            #
                          
                          
                             等同于下面
                          
                          
path(
                          
                            '
                          
                          
                            login
                          
                          
                            '
                          
                          ,views.view)    
                          
                            #
                          
                          
                             看着是不是与普通的路由没有什么区别了 : 通过匹配触发视图函数的运行
                          
                        

那么  view  是一个什么样的函数呢? 现在突破口变成了  view  方法了 。

我们再看其源码(只看框起来的即可,其他的不用管)

                          
                            "
                          
                          
                            self = cls(**initkwargs)
                          
                          
                            "
                          
                          
                            #
                          
                          
                             cls是什么? 记得上面的类方法吗? 类调用时传入类本身
                          
                          
                            
#
                          
                          
                             我们是通过MyView来调用as_view的, 那么cls也就是MyView
                          
                          
                            
#
                          
                          
                             类加括号实例化得到对象self, 这个self就是我们自己的类产生的对象 : self=MyView(**initkwargs),我们不用去管里面的参数
                          
                          
                            
#
                          
                          
                             接下来看看view的返回值 : self.dispatch(request, *args, **kwargs)
                          
                          
                            
#
                          
                          
                             也就是去MyView类实例出的对象里面去找dispatch方法并执行,很显然self对象中没有该方法,于是去类中去找,也没有
                          
                          
                            
#
                          
                          
                             最后到父类View中去找,发现就在as_view类方法的下面找到了
                          
                        

  。

 我们在看它下面的逻辑代码 。

  。

 逻辑很简单,使用了反射的知识点 。

                          
                            #
                          
                          
                             先是拿到当前请求方式的大写字符转成小写, 然后判断在不在后面的 self.http_method_names 里面
                          
                          
                            
#
                          
                          
                             Ctrl+点击 看看这是个什么东西 : 
                          
                          
                            '
                          
                          
                            http_method_names = [
                          
                          
                            '
                          
                          get
                          
                            '
                          
                          
                            , 
                          
                          
                            '
                          
                          post
                          
                            '
                          
                          
                            , 
                          
                          
                            '
                          
                          put
                          
                            '
                          
                          
                            , 
                          
                          
                            '
                          
                          patch
                          
                            '
                          
                          
                            , 
                          
                          
                            '
                          
                          delete
                          
                            '
                          
                          
                            , 
                          
                          
                            '
                          
                          head
                          
                            '
                          
                          
                            , 
                          
                          
                            '
                          
                          options
                          
                            '
                          
                          
                            , 
                          
                          
                            '
                          
                          trace
                          
                            '
                          
                          
                            ]
                          
                          
                            '
                          
                          
                            #
                          
                          
                             发现是8种常用的请求方式列表, 接着返回dispatch源码查看,为了方便我们假设现在的是get请求方式
                          
                          
                            
#
                          
                          
                             判断get请求在请求列表里面,于是执行紧跟其下的代码...我们先看看getattr()得到的是什么结果
                          
                          
                            
#
                          
                          
                             判断我们的self是否有名叫get的属性或方法,如果有则返回该属性的值或方法的内存地址,否则返回 self.http_method_not_allowed, 这是个啥,我们 Ctrl+点击 也来看看:
                          
                        

                          
                            #
                          
                          
                             原来是一个报错信息 : 提示方法不允许,整理下思路,也就是说self中有get返回值或者内存地址,没有则报错
                          
                          
                            
#
                          
                          
                             很显然我们的self是有get这个名字的,并且是一个方法,于是将get方法的内存地址赋值给handler
                          
                          
                            
#
                          
                          
                             我们再来看dispatch的返回值 : handler + (括号), 不就是执行该方法吗!也就是执行了我们的get方法打印了"触发了get方法--->"
                          
                        

  。

最后此篇关于Django之视图层的文章就讲到这里了,如果你想了解更多关于Django之视图层的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com