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 也是一个类,请看下图解析"""
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)
request对象获取文件
form表单携带文件类型的数据 需具备下列条件
1. form表单的method必须是post
2. form表单的enctype 必须是form-data
<form action="" method="post" enctype="multipart/form-data">
django后端需要通过request.FILES获取文件类型的数据
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拿到方法后 并调用方法