视图层

内容概要

  • 视图层之必会三板斧
  • 视图层之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表单携带文件类型的数据需要做到以下几点

  1. method必须是post
  2. 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请求')

可以看出CBVFBV更灵活一些

会根据请求方式的不同自动匹配不同的对应方法并执行

CBV源代码剖析(重要)

  1. 从CBV的路由匹配切入

    path('login/', views.MyLoginView.as_view())

    1. 类名点名字(名字的查找问题)
    2. 类名点名字并括号调用(静态方法、绑定给类的方法)
  2. 函数名加括号执行优先级最高 项目一启动就会自动执行as_view方法

  3. 浏览器地址栏login路由会自动执行view函数

    1. 产生我们自己编写类的对象
    2. 对象调用dispatch方法(注意查找顺序)
  4. 讲究父类中的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把它的值返回

posted @ 2022-12-13 21:29  可否  阅读(32)  评论(0)    收藏  举报