视图层

视图函数返回值

视图函数都必须返回一个HttpResponse对象。

首先是之前说的三个返回方法:HttpResponse、render、redirect。

HttpResponse肯定返回的是一个HttpResponse对象,事实上,render()和redirect()方法返回的都是一个HttpResponse对象,我们可以查看这两个方法的源码进行查看。

比如render()方法源码:
image

redirect()方法往更深的源码去查看,这里不方便演示。

JsonResponse对象

除了HttpResponse、render、redirect这三个可以给视图函数设置返回值,还有一个JsonResponse也可以,它用于返回一个json格式的数据。

from django.http import JsonResponse
def index(request):
    user_dict = {'name':'tom', 'age':18, 'hobby':'读书'}
    return JsonResponse(user_dict)

image

此时的中文是无法正常显示的,我们需要添加参数才能正常显示:

from django.http import JsonResponse
def index(request):
    user_dict = {'name':'tom', 'age':18, 'hobby':'读书'}
    return JsonResponse(user_dict, json_dumps_params={'ensure_ascii':False})

image

如果想要把其他类型转成json格式发送,需要把JsonResponse方法的safe参数设置为False

from django.http import JsonResponse
def index(request):
    l = [11, 22, 33]
    return JsonResponse(user_dict, safe=False)

form表单上传文件

form表单上传的数据中如果含有文件,那么需要以下要求:

  1. 表单属性method必须是post
  2. 表单属性enctype必须修改为multipart/form-data
  3. 后端需要使用request.FILES获取

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form method="post" enctype="multipart/form-data" action="">
    <input type="file" name="my_file">
    <input type="submit">
</form>
</body>
</html>

views.py

def index(request):
    if request.method == 'POST':
        print(request.FILES)  # 专门获取文件数据
        file_obj = request.FILES.get('my_file')  # 根据你的input标签的name属性获取
        print(file_obj.name)  # 查看文件名
        with open(file_obj.name,'wb') as f:  # 直接通过文件名保存本件
            for line in file_obj:
                f.write(line)

    return render(request, 'index.html')

request方法

request方法 作用
request.method 获取请求方法
request.POST 获取POST请求数据
request.GET 获取GET请求数据
request.FILES 获取文件数据
request.body 获取最原始请求数据(二进制数据)
request.path 获取地址后缀路径,但不会获取路径后面携带的参数
request.path_info 与request.path一致
request.get_full_path() 获取地址后缀路径并且还可以获取到路径后面携带的参数

FBV与CBV

FBV即基于函数的视图,CBV即基于类的视图。我们之前一直都是使用FBV。

CBV使用

视图层(views.py)

from django import views
class MyView(views.View):
    def get(self, request):
        return HttpResponse("from CBV get view")
    def post(self, request):
        return HttpResponse("from CBV post view")

路由层(urls.py)

urlpatterns = [
    url(r'^index/', views.MyView.as_view()),
]

image

如果请求方式是GET,则会自动执行类里面的get方法;如果请求方式是POST,则会自动执行类里面的post方法;

CBV源码剖析

想详细了解CBV源码我们可以从路由层出发。

1.首先views.MyView.as_view()很明显是调用了类里面的as_view方法,在pycharm中按住ctrl点击as_view()查看详情。

2.因为我们在类中并没有定义as_view方法,所以这是父类Views中的方法。

image

3.as_view()返回的是一个view函数,说明路由匹配成功执行了view函数,然后我们在细看view函数。

image

4.view函数返回了一个dispatch()方法,并且是用我们自己的类实例化得到的对象调用的,我们的类中没有dispatch()这个方法,所以这个明显又是父类Views中的方法。

5.查看dispatch()详情

image

6.request.method这个方法我们都知道,用于返回请求方法的,这里进行了一个判断:判断请求方法是否在http_method_names中。

7.我们再来看看http_method_names有哪些内容。

image

8.再回到dispatch()方法if判断中,说如果request.method在http_method_names中,就使用getattr()获取对象中的方法,最后在return那里调用并返回。

总结:也就是说,如果请求的方法(request.method)在http_method_names中,就会调用我们类中的对应的方法。

CBV添加装饰器

如果想要给CBV添加装饰器需要借助一个专门的装饰器模块:method_decorator

导入:

from django.utils.decorators import method_decorator

方式一:直接在类中的某个方法上添加

class MyCBV(views.View):
    @method_decorator(装饰器名称)
    def get(self, request):
        return HttpResponse("from CBV get view")

方式二:直接在类上添加,并指定内部方法

@method_decorator(装饰器名称,name='get')
@method_decorator(装饰器名称,name='post')
class MyCBV(views.View):
    def get(self, request):
        return HttpResponse("from CBV get view")
    def post(self, request):
        return HttpResponse("from CBV post view")

方式三:重写dispatch方法并添加装饰器,这会作用于类中所有的方法

class MyCBV(views.View):
    @method_decorator(装饰器名称)
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)
posted @ 2022-05-13 18:06  Yume_Minami  阅读(86)  评论(0编辑  收藏  举报