Django之视图函数层 (必会三板斧 JsonResponse对象 request对象获取文件 FBV与CBV CBV源码剖析)

发布时间 2023-04-25 21:31:43作者: 南柯unique

目录

视图层之必会三板斧

用来处理请求的视图函数都必须返回HttpResponse对象
  • 情况一:啥也不返回
    image
    这里会报一个没有返回HttpResponse对象的错误,由此可见必须要返回一个HttpResponse对象
    image
  • 情况二:返回HttpResponse对象
    点击Ctrl键查看源码可见是HttpResponse类,所以会返回一个值
    image
  • 情况三:返回render对象
    点击Ctrl键查看源码可见是render返回的是HttpResponse对象
    image
  • 情况四:返回redirct对象
    点击Ctrl键查看源码可见是redirect最终有个祖先类返回的是HttpResponse对象
    image

视图层之JsonResponse对象

  • 如果返回浏览器的是中文,则要看源码,去给json_dumps_params={'ensure_ascii': False}加参数
    image
from django.http import JsonResponse
user_dict = {'username': 'tank哈哈哈', 'age': 20}
json_str = JsonResponse(user_dict, json_dumps_params={'ensure_ascii': False})
  • 如果返回浏览器的是列表,根据看报错信息,则要看源码,去给safe=False改参数
    image
l = [1,2,3,4]
json_str = JsonResponse(l,safe=False)

视图层之request对象获取文件

  • 表单上传问价需要满足的条件是:
  1. 请求方式method必须是:post
  2. enctype必须是multipart/form-data
    django后端需要通过request.FILES获取文件类型的数据
<form action="" method="post" enctype="multipart/form-data">

def ab_file(request):
    # 接收用户提交过来的数据
    # request.POST 只能接收普通参数,不能接收文件数据
    print(request.POST) # <QueryDict: {'username': ['SDASD']}>
    # 如何接收文件数据
    print(request.FILES) # <MultiValueDict: {'myfile': [<InMemoryUploadedFile: 123.png (image/png)>]}>
    file_obj = request.FILES.get('myfile')
    with open(file_obj.name, 'wb') as f:
        # f.write(file_obj)
        for line in file_obj:
            f.write(line)
    return render(request, 'ab_file.html')

视图层之FBV与CBV

  • FBV
  •   基于函数的视图
    
	def index(request):
		return HttpResponse对象
  • CBV
  •   基于类的视图
    
	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')
	path('login/', views.MyLoginView.as_view())
	# 会自动根据请求方法的不同自动匹配对应的方法并执行

CBV源码剖析(重点)

执行流程版本(一):

  1.   路由配置:path(r'test/', views.Test.as_view()),

  2.   请求通过中间件后进入路由--->根据路由匹配,一旦成功,会执行后面函数(request)--->

  3.   本质就是执行了as_view内部的view函数---->内部又调用了self.dispatch---->

  4.   根据请求方式,执行不同的方法(必然get请求,就会执行咱么写的视图类的get方法)

执行流程版本(二):

1.从CBV的路由匹配切入 path('login/', views.MyLoginView.as_view())
①.类名点名字(名字的查找问题)
②.类名点名字并加括号调用(静态方法、绑定给类的方法)*
2.函数名加括号执行优先级最高 项目一启动就会自动执行as_view方法path('login/', views.view) CBV路由本质还是FBV
3.浏览器地址栏访问login路由需要执行view函数
①.产生我们自己编写类的对象
②.对象调用dispatch方法(注意查找顺序)
4.研究父类中的dispatch方法
获取当前请求方法并转小写 之后利用反射获取类中对应的方法并执行

分析

先创建一个视图类

image

配置路由

image

然后按住ctrl键点进去看as_view的源码

image

这里的self是view这个类的对象,我们在类视图继承了view这个类,就是我们Test这个类的对象,这里返回了一个dispatch方法,但是我们并没有定义这个方法,所以就去Test的父类View里面去找

image

然后再来分析

image

找到dispatch

image

如果在这里面通过反射getattr去这self这个对象里也就是Test这个类的对象通过传过来的名字比如get去取东西,所以类里面的get必须带request

image

views.Test.as_view()-------------------->View类里面的as_view方法中得view方法的内存地址

image