简单模拟Django中的View类

2024年04月14日 django Python51

最近一直用Django开发项目,在项目的视图中使用到了Django的View类和ListView类。

from django.views.generic import View, ListView

在使用过程中,发现Django的View类中有两个方法可以重写,分别是get()和post()。

当我们继承View类,并重写上述的两个方法时,View类就能够自动根据request请求中的method类型自动调用相应的方法。

比如,打开登录页面。

路径:../login/

method:GET

urls:path(‘login/’, view.LoginView.as_view())

views:

class LoginView(View):
    template_name = 'login.html'

通过以上代码,就完成了打开登录页面相关代码的编写。

再比如,打开登录页面之后的登录验证。

路径:../login/

method:POST

urls:path(‘login/’, views.LoginView.as_view())

views:

class LoginView(View):
    template_name = 'shop/login.html'

    def post(self, request):
        ...此处省略登录验证的代码...

大家能够看到,登录验证的路径和URL配置没有任何改变,只是请求方法变成了“POST”,并且在视图中重写“post()”方法就可以了。

一般来说,我们在写视图函数时,URL配置中都是“views.视图函数名称”,例如,“views.login”。

而使用Django的View类时,URL配置中都是“views.视图类名称.as_view()”,例如,“views.LoginView.as_view()”。

这里很容易让人产生矛盾,为什么一个没有括号,一个有括号?

我们知道,一个没有括号的函数名称,表示一个函数对象;而有括号的函数名称是函数对象被执行。

“views.login”是视图模块中的函数对象,当收到request请求时,会将request作为参数执行这个函数。

那为什么使用Django的View类时,URL配置中不是函数对象,而是执行了一个函数呢?

实际上执行的“as_view()”是一个类方法(classmethod),它会返回一个函数对象(闭包)。

下面,我通过一段代码给大家简单的模拟一下基本原理。

示例代码:

class SiteBaseView:
    template_name = ''  # 定义模板名称的类变量

    def get(self, request):  # 与request请求类型同名的方法
        return render(request, self.template_name)

    def post(self, request):  # 与request请求类型同名的方法
        pass

    def dispatch(self, request):  # 5B.被执行的调度方法
        method = getattr(self, request.method.lower())  # 6.获取与request请求类型同名的方法对象
        return method(request)  # 7.执行方法对象并返回执行结果

    @classmethod
    def as_view(cls):  # 1.urls中执行的类方法
        def view(request):  # 3.被返回的函数对象
            self = cls()  # 4.创建类对象
            response = self.dispatch(request)  # 5A.执行类对象中的调度方法
            return response  # 8.返回响应结果

        return view  # 2.返回函数对象

完成以上代码后,我们就可以在定义视图类时,像继承Django的View类一样,继承我们自己写的“SiteBaseView”类。

示例代码:

class LoginView(SiteBaseView):
    template_name = 'shop/login.html'

    def post(self, request):
        ...此处省略登录验证的代码...

最终的运行效果是一样的。

不过,在这里我只是通过简单的代码来模拟实现原理,Django的View类要比上面的代码复杂得多,大家可以通过研究Django的源代码学到更多有用的知识。

本文链接:http://so.lmcjl.com/news/2093/

展开阅读全文