django之视图层

django之视图层

视图函数结构

视图函数的参数与返回值

每一个用来处理请求的视图函数,默认都需要一个request形参来接收request对象。

每一个用来处理请求的视图函数必须返回一个HttpResponse对象,包括我们三个响应函数:

  • HttpResponse(一些数据)

    def func1(request):return HttpResponse("返回给网页的内容")

  • render(request, "html模板",{模板数据字典})

    def func2(request):return render(request,"aaa.html",{"useronfo":userinfo,})

    处理模板语法,返回html页面内容。
    第一个参数传入request对象,第二个参数传入含有模板语法的html文件名(templates目录下),第三个参数则是传入模板语法可能用到的数据,我们可以通过字典的方式传入,也可以使用local()\global()直接获取局部或者全局的所有名字传进去,好处是我们不必在给数据命名了,坏处是传数值不够精准,可能会浪费资源。

  • redirect(重定向的网址)

    def func3(request):return redirect("/home")

    重新向指定网址发送一个请求,内部的网址有三种形式:

    "/路由":拼接域名和路由形成一个网址
    "完整网址":本身就是域名+路由的形式的网址
    
  • JsonResponse(python数据)

    from django.http import JsonResponse
    def func4(request):
        return JsonResponse({'a':'aaa','b','bbb'})  # 将Python字典数据处理成Json数据传给前端
    
    def func5(request):
        user_dict = {'a':'大爷','b','bbb'}
    	# 查源码可知,可以书写json序列化的参数,也可以让python数据不局限于字典
        return JsonResponse(user_dict, json_dumps_params={ensure_ascii:False},safe=False)
    

    对json源码的简析:

    def __init__(self, data, encoder=DjangoJSONEncoder, safe=True,
                 json_dumps_params=None, **kwargs):
        if safe and not isinstance(data, dict):  # safe默认为真,为真时,只接收字典数据
            raise TypeError(
                'In order to allow non-dict objects to be serialized set the '
                'safe parameter to False.'
            )
        if json_dumps_params is None:  # 如果没有传入json序列化相关参数,就设置为空字典
            json_dumps_params = {}
        kwargs.setdefault('content_type', 'application/json')
        data = json.dumps(data, cls=encoder, **json_dumps_params)
        super().__init__(content=data, **kwargs)

关于返回值为HttpResponse对象这一点

第一个我们尚可理解,因为HttpResponse就是一个类,它所产生的的对象就是HttpResponse对象,我们将其返回出去,并最终传到浏览器,经过http渲染变成用户可以看到的内容。

后面三个是函数,而底层实际上是将函数的返回值设置为了HttpResponse对象。

视图函数request对象

我们可以通过路由层传输过来的request对象获取:

  • GET:get请求携带的数据
  • POST:post请求携带的数据
  • FILES:表单标签提交的文件数据

form表单携带文件类型数据可以在form表单中添加两个属性:

  • method属性得是post(因为文件大小一般较大)
  • enctype属性可以是multipart/form-data

这样我们就可以通过request.FILES得到一个文件字典,键为input标签的name属性,值为input标签提交的文件对象,我们可以对文件进行保存、读取等操作。

视图函数逻辑功能

视图函数作为我们的后端函数,它肩负着处理数据逻辑的功能,这也需要它能与数据库打交道,在请求生命流程图中也提到了,视图层通过模型层可以绕开sql语句来与对数据库的表进行增删改查。

而除了处理数据的逻辑,我们也需要对前端界面的一些元素做动态的处理,如将我们后端的变量数据传到前端页面中,或者对前端页面的某些标签做逻辑的处理,这些则需要用到模板语法了,在django项目中,这个工作就是通过render做的,它接收html页面和后端数据,对页面中的模板语法进行识别做后端的处理,最终将处理完的页面打包为HttpResponse对象。

视图层之FBV和CBV

FBV(fuction based view):基于函数的视图,上文所说的都是FBV

CBV(class based view):基于类的视图吗,与FBV有些许的不同。

CBV结构

视图文件中:

from django import views
class MyLoginView(views.View):  # 视图类必须继承views.View
    def get(self, request):  # 根据请求方式命名的类体函数
        return HttpResponse('from CBV get function')  # 返回的还是HttpResponse对象

    def post(self, request):
        return HttpResponse('from CBV post function')

路由文件中:

from apps import views

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

通过上面的代码得知,实际上CBV本质还是FBV,最终路由所索引到的函数还是视图类中的某个视图函数。

CBV源码剖析

  1. views.MyLoginView.as_view()与其他路由所对应的视图函数相比,CBV路由所对应的是视图类的某个方法,而这个as_view并不在我们定义的类中。那么as_view很有可能是我们继承的父类View中的,我们ctrl键跟上去查看。

    img

    发现,as_view的返回值是一个函数,与我们其他路由所对应的视图函数相呼应,我们可以猜测这个函数返回值是一个视图函数。

  2. 带着这个猜想我们展开view函数进行查看:

    img

    发现这个返回值仍然不是一个明确的函数,我们还需要查看dispatch方法的返回值,在此之前,我们需要分析出,dispatch是绑定对象的动态方法,这个self是由我们自己定义的类所产生的对象。

  3. 查看dispatch函数,由于我们对象及其类的属性中都没有dispatch,所以这个函数还是我们父类View的类体函数:

    img

至此,我们就剖析出,我们的as_view()函数做了这么几件事:

  • 封装了一个函数,作为对应路由的函数
  • 封装的函数中,让我们的自定义类产生了一个对象,并让对象执行方法dispatch返回结果
  • dispatch辨认了请求方式,根据请求方式返回了某个类体函数的结果(HttpResponse对象)

所以视图类,就是将一个路由根据请求方式又重新划分了不同的视图函数,不必再在视图函数中对请求方式进行判断了。

posted @ 2023-06-26 15:29  wwwxxx123  阅读(4)  评论(0编辑  收藏  举报