视图层
内容概要
- 视图层之必会三板斧
- 视图层之JsonResponse对象
- 视图层之request对象获取文件
- 视图层之FBV与CBV
- CBV源码剖析
视图层必会三板斧
用来处理请求的视图函数都必须返回HttpResponse对象
class HttpResponse:
pass
def render():
return HttpResponse()
return render()
def redirect():
redirect_class = 类(祖先有个类是HttpResponse)
return redirect_class()
return redirect()
JsonResponse对象
def index_func(request):
# print(reverse('wuhu'))
# print(reverse('app01:wuhu'))
# print(reverse('app01_wuhu'))
# 返回浏览器一个json格式的字符串
import json
user = {'name': 'jason', 'age': 18}
user_json = json.dumps(user)
return HttpResponse(user_json)

from django.http import JsonResponse
def index_func(request):
user = {'name': 'jason', 'age': 18}
return JsonResponse(user)

可以看出来 浏览器更推荐你使用JsonResponse
但是我们传中文的时候
from django.http import JsonResponse
def index_func(request):
user = {'name': 'jason老师', 'age': 18}
return JsonResponse(user)

会变成乱码 我们用json的时候也会我们是写了一个参数ensure_ascii = False
但是这个JsonResponse怎么办呢
可以去看一下它的源码

它的内部也是用dumps转成json字符串的

可以看到里面的源码 第二不如果为空则等于空字典
然后第三步把它打散
打散成关键参数 字典的键等于字典的值的形式所以我们就可以这么写
from django.http import JsonResponse
def index_func(request):
user = {'name': 'jason老师', 'age': 18}
return JsonResponse(user, json_dumps_params={'ensure_ascii': False})

当我们去序列化别的数据
def index_func(request):
# user = {'name': 'jason老师', 'age': 18}
user = [1,2,3, 4,]
return JsonResponse(user, json_dumps_params={'ensure_ascii': False})

报错
:为了允许序列化非dict对象,请将安全参数(safe)设置为False
所以我们当我们要序列化非字典的时候
def index_func(request):
user = [1,2,3, 4,]
return JsonResponse(user, safe=False)

JsonResponse主要序列化字典 针对非字典的其他操作可以被序列化的数据修改safe参数为False
视图层之request对象获取文件
当我用django上传文件的时候

def upload_func(request):
name = request.GET.get('name')
pwd = request.GET.get('pwd')
file = request.GET.get('file')
print(name)
print(pwd)
print(file)
return render(request, 'upload_file.html')

可以获取普通数据,文件只获取了一个文件的名字
form表单携带文件类型的数据需要做到以下几点
- method必须是
post - enctype必须是
multipart/form-data
django后端需要通过request.FILES获取文件数据类型的数据
def upload_func(request):
if request.method == 'POST':
name = request.POST.get('name')
pwd = request.POST.get('pwd')
file = request.FILES
print(name)
print(pwd)
print(file)
return render(request, 'upload_file.html')
jason
4dzj
<MultiValueDict: {'file': [<InMemoryUploadedFile: image-20220927171634916.png (image/png)>]}>

我们可以发现这个跟我们直接打印request.POST的数据挺像的
它也有get方法我们可以列表里面的数据也支持for循环
def upload_func(request):
if request.method == 'POST':
file = request.FILES.get('file')
import os
from django04 import settings
file_dir = os.path.join(settings.BASE_DIR, 'app01', 'file')
with open('%s/12.jpg'% file_dir, 'wb')as f:
for i in file:
f.write(i)
return render(request, 'upload_file.html')

视图层之FBV与CBV
FBV(function based views)
基于函数的视图
我们之前写的都是FBV
CBV(class based views)
基于类的视图
from django import views
class MyClass(views.View):
def get(self, request):
return HttpResponse('这是GET请求')
def post(self, request):
return HttpResponse('这是POST请求')


可以看出CBV比FBV更灵活一些
会根据请求方式的不同自动匹配不同的对应方法并执行
CBV源代码剖析(重要)
-
从CBV的路由匹配切入
path('login/', views.MyLoginView.as_view())- 类名点名字(名字的查找问题)
- 类名点名字并括号调用(静态方法、绑定给类的方法)
-
函数名加括号执行优先级最高 项目一启动就会自动执行as_view方法
-
浏览器地址栏login路由会自动执行view函数
- 产生我们自己编写类的对象
- 对象调用
dispatch方法(注意查找顺序)
-
讲究父类中的
dispatch方法获取当前请求方法并转小写 之后利用反射取类中对应的方法并执行
def view(request, *args, **kwargs):
self = cls(**initkwargs)
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)

会先找自己 有没有as_view()这个方法






看一下这个函数体代码
它是先判断请求方式 请求方式是否在self.http_method_names里面
如果在里面 就去找这个self里面有没有与当前这个请求方式名字一样的方法 如果有则把这个方法的名字赋值给 handler 如果没有则把self.http_method_names 的值赋值给handler
如果不在里面则直接把self.http_method_names 的值赋值给handler
最后调用handler把它的值返回



浙公网安备 33010602011771号