django 视图层

简介:
视图层三板斧详解,JsonResponse对象,request对象获取文件,FBV与CBV,CBV源码剖析

视图层

视图层三板斧详解

研究: 用来处理请求的视图函数都必须返回HttpResponse对象

return HttpResponse()
研究源码发现 HttpResponse发现它是一个类 , 返回的时候+括号了 就等于类+括号,会产生一个对象。

return render()
查看源码发现render是一个函数,在函数内部返回了一个HttpResponse() (调用了) 那么它也是一个HttpResponse对象

return redirect()
查看源码发现 redirect也是个函数 其内部有一个三元表达式,
def redirect(to, *args, permanent=False, **kwargs):
	HttpResponsePermanentRedirect if permanent else HttpResponseRedirect
其参数默认是不成立的,不成立则使用值2  在研究值2的源码发现其父类的父类继承了HttpResponse ,本质上也是一个HttpResponse对象

JsonResponse对象

它的作用用来给前端返回json格式的字符串

1.不用jsonResponse对象返回json格式方法
def json_dict(request):
    user_dict = {'name':'liaji李阿鸡','age':18,}
    import json
    user_date= json.dumps(user_dict,ensure_ascii=False)  # ensure_ascii 序列化时不进行转码
    return HttpResponse(user_date)

2.使用JsonResponse对象进行返回
from django.http import JsonResponse
def json_dict(request):
    user_dict = {'name':'liaji李阿鸡','age':18,}
    return JsonResponse(user_dict)
但是自动把中文转码了
"""研究源码:发现 JsonResponse 也是一个类,请看下图解析"""

image

return JsonResponse(user_dict,json_dumps_params={'ensure_ascii':False})

默认针对字典做序列化 如果使用其他数据类型做系列化发现有报错信息
from django.http import JsonResponse
def json_dict(request):
    l1 = [11,22,33,44]
    return JsonResponse(l1,json_dumps_params={'ensure_ascii':False},)
    "访问页面出现报错 请看下图"
     # 研究JsonResponse源码发现确实有safe参数
    return JsonResponse(l1,json_dumps_params={'ensure_ascii':False},safe=False)

image

request对象获取文件

form表单携带文件类型的数据 需具备下列条件
1. form表单的method必须是post
2. form表单的enctype 必须是form-data
 <form action="" method="post" enctype="multipart/form-data">
    
django后端需要通过request.FILES获取文件类型的数据

image

FBV与CBV

FBV

FBV就是我们现在所用的 在视图层里编写函数。称为: 基于函数的视图

CBV

基于类的视图

顾名思义就是在视图层里编写类

# CBV 路由层写法
path('login/',views.MyloginView.as_view())


# 视图层写法
class MyloginView(views.View):
def get(self,request):   # 编写跟请求方法相同的 功能
    return HttpResponse('get 方法')
def post(self,request):  # 编写跟请求方法相同的 功能
    return HttpResponse('post 方法')
# CBV自动判断请求方式并执行   

CBV源码剖析

了解CBV如何自动判断请求方式

首先想要了解一个源码就要找准切入口
因为视图层中的类继承的view 我们可以理解成一个父类
从路由层的as_view()这里我们看不懂 就从这里开始查看源码
1.路由层中使用MyloginView来点as_view这个名字,我们回想名称空间的知识点类(对象)点一个名字的查找顺序  对象自身名称空间-产生对象的类的名称空间-产生类的父类的名称空间 我们查看我们写的类并没有这个名字
    as_view() 可以想象要么是个无参函数,要么是个绑定给类的方法,类来调把类当做参数传过去"函数名+()优先级最高 匹配到路由就会先执行as_view()"
我们查看as_view的源码发现是个绑定给类的方法 并且返回值是view
此时我们的path('login/',views.MyloginView.as_view()) 就会变成
('login/',views.view)  # 访问login/就会执行 views.view函数


2.研究view函数
        def view(request, *args, **kwargs):
            self = cls(**initkwargs) # cls是我们自己写的类,因为as_view是绑定给类的方法会自动把类当做参数传过来,类() 产生一个我们自己类的对象
            if hasattr(self, 'get') and not hasattr(self, 'head'):
                self.head = self.get
            self.setup(request, *args, **kwargs)
            if not hasattr(self, 'request'):
                raise AttributeError(
                    "%s instance has no 'request' attribute. Did you override "
                    "setup() and forget to call super()?" % cls.__name__
                )
            return self.dispatch(request, *args, **kwargs)  
			# self是我们自己编写的类产生的对象。
我们的自己编写的类产生的对象.dispatch 名字 按照查找顺序我们查找发现他在view类里是一个函数

3. 研究父类view 里的 disptch函数
http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
    def dispatch(self, request, *args, **kwargs):
        if request.method.lower() in self.http_method_names: # 把当前请求方式转成小写并判断是否在方法列表里
            handler = getattr(self, request.method.lower(), self.http_method_not_allowed)  # 用getaattr 反射方法 拿到我们对象中的请求方法  
"第一个参数我们的对象,第二个参数当前请求方法并转小写,最后一个参数是获取不到的报错信息"
        else:
            handler = self.http_method_not_allowed
        return handler(request, *args, **kwargs)  # getattr拿到方法后 并调用方法
posted @ 2022-12-13 19:50  李阿鸡  阅读(16)  评论(0编辑  收藏  举报
Title