django——视图层

django——视图层

目录:

  • 三板斧

  • JsonResponse

  • form表单上传文件

  • FBV与CBV

  • CBV源码

视图函数的返回值

视图函数必须返回一个HttpResponse对象

HttpResonse的本质就是一个类

  • 解析为什么必须返回一个HttpResponse

    在返回值后面的三板斧(render(返回一个网页地址)、HttpResponse(返回一个文本)、redirect(重定向))中,其调用的内置函数中,结果都会有一个返回值HttpResponse

    1. render
    def render():
        return HttpResponse(...)
    class HttpResponse(HttpResponseBase):
          pass
        
    2.HttpResponse
    def 自定义():
        return HttpResponse(...)
    
    3.redirect
      def redirect(to, *args, permanent=False, **kwargs):
            redirect_class = HttpResponsePermanentRedirect if permanent else HttpResponseRedirect
            return redirect_class(resolve_url(to, *args, **kwargs))
        
    

    三者之中都会调用HttpResponse这个类,故而是必须返回一个HttpResponse

返回json格式数据

  • JsonResponse()方法

    使用JsonResponse()方法就相当于将该数据使用 json序列化,将该数据序列化为json格式的数据

    user_dict = {'name': 'jason老师', 'pwd': 123, 'hobby': ['read', 'run', 'music']}
       json_str = json.dumps(user_dict, ensure_ascii=False)
       return HttpResponse(json_str)
       return JsonResponse(user_dict)
    

    ​ 得出的结果大致一致,在有文本的时候,JsonResponse()类中需要添加一个参数'ensure_ascii':False 取消默认编码

  • 修改取消默认编码的参数

    1.首先进入JsonResponse方法的源码中
    def __init__(self, data, encoder=DjangoJSONEncoder, safe=True,
                 json_dumps_params=None, **kwargs):
    
        if json_dumps_params is None:
            json_dumps_params = {}
    
        data = json.dumps(data, cls=encoder, **json_dumps_params)
        super().__init__(content=data, **kwargs)    
     # 这里的 json_dumps_params默认为{},需要再调用的时候在外部传参将默认编码的形式做出更改
    
     JsonResponse(user_dict, json_dumps_params={'ensure_ascii':False})
        
    

    注意:这里使用JsonResponse()方法只能转码字典形式,若想转码其他形式的数据时需要修改参数

  • 当数据类型不为字典形式时修改的参数

    JsonResponse主要是用于字典的序列化,若遇到其他类型需要序列化,需要将JsonResponse源码中的默认值safe=True,改为safe=False;
     JsonResponse(user_dict, json_dumps_params={'ensure_ascii':False}, safe=False )
    

form表单携带文件数据

  • form表单需要具备的条件

    <form action="" method="POST" enctype="multipart/form-data">    
    </form>
    

    1.method属性值必须是post

    2.enctype属性值必须是multipart/form-data

    满足两种属性值才可以对文件进行操作,否者只会得到其文件命

  • 后端获取文件数据

    res = request.FILES.get('前端设置的文件的接受名')
    # 保存文件数据
    with open(res.name,'wb') as f:
        for line in res:
            f.write(line)  # 将文件保存到后端
            
    

    操作类似于request.POST

FBV与CBV

FBV与CBV的区别

类别 区别
FBV 基于函数的视图
CBV 基于类的视图

FBV

FBV就是在视图层中,以函数来书写其业务逻辑

 def index(request):
      return HttpResponse()

在路由层设置接口      
path('index/', views.index)

CBV

CBV就是在视图层中,以类来书写其业务逻辑

from django import views
class MyView(views.View):      # 导过来的模块中有view这个类,需要继承这个类
    def get(self, request):
        return HttpResponse('我是CBV里面的get方法')
    def post(self, request):
        return HttpResponse('我是CBV里面的post方法')
    
路由层设置接口
path('func/', views.MyView.as_view())
    
    """这里的方法的名字是固定的, CBV会自动根据请求方式的不同匹配类中定义的方法并自动执行"""

CBV的源码

  1. CBV 源码分析入口:

    路由层中的路由匹配 path('func/', views.MyView.as_view())

  2. 类或对象在点属性的方法时,查找顺序是先找自身,若没有,在找这个方法的父类

  3. 进入as_view源码层寻找到其父类view,而view在设置的类中

  4. 绑定给类的as_view方法

    @classonlymethod
    def as_view(cls, **initkwargs):   # 绑定给类,类来调取的时候,将类当成第一个形参传入
        def view(...):
            pass
        return view
    

    只有一个返回值,而且返回的是view方法的结果view,

    调用方法后,MyView.as_view()的结果为view

  5. 此时的路由匹配的结果为

    path('func/', views.view)
    

    故而CBV路由匹配本质:跟FBV是一致的

  6. 访问func触发view执行

    def view(...):
        obj = cls()			# 这里的cls是自己所定义的类,类加括号产生一个对象
        return obj.dispatch()	
    # 返回自己所写类中是否有dispatch方法,有则直接运行,没有则查找其父类
    
  7. 研究dispatch方法

    http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
    
    def dispatch(...):
        # 先判断是否在常见的请求方法中
        if request.method.lower() in self.http_method_names:    
            func_name = getattr(obj,request.method.lower())
         # 请求方法的函数名 = geattr(对象,'请求方法')   
            func_name(...) # 最后执行操作
    
posted @ 2022-09-02 20:49  Nirvana*  阅读(29)  评论(0)    收藏  举报