Django类视图CBV,as_view源码剖析,类视图的基本使用案例

Django类视图(CBV)

FBV(function base views) 基于函数的视图,就是在视图里使用函数处理请求。

CBV(class base views) 基于类的视图,就是在视图里使用类处理请求。

在前面,已经使用了FBV视图,在定义函数阶段,只要定义参数request,并且绑定响应的路由,就可以做到视图与路由的绑定

但是函数视图对于复杂项目,用起来更加繁琐,无法实现更加方便的面向对象,并且可以配合Django实现Mixin类型。

而CBV视图,在大规模项目中,用起来更加方便简单。

1. 类视图的基本用法

类视图与函数视图不一样,我们需要实现以下几种定义

  1. 函数中为不同的HTTP请求方法单独定义函数,例如接受POST请求,就需要类中定义post函数,以此类推
  2. 类视图必须继承自 django.views.View 父类
  3. 类视图的请求入口,通过类中的as_view()静态方法实现->View 父类 已经定义

这里简单实现一个登录接口的类视图

注意事项!!as_view必须带括号!!!

urls.py

from django.urls import path
import user.views

urlpatterns = [
    path("admin/", admin.site.urls), # 基于FBV视图的实现,不需要带括号
    path("login/", user.views.UserLogin.as_view(), name='login'),  # as_view要带括号
]

views.py

from django.views import View
from django.http import HttpResponse
from . import *

class UserLogin(View):
	"""
		必须继承View父类
	"""
    def get(self, request):
    	"""
    		定义get请求时返回一个login.html
    	"""
        return render(request, 'login.html')

    def post(self, request):
    	"""
    		定义post请求时返回登录结果,并添加上session
    	"""
        username = request.POST.get('username').lower()
        password = request.POST.get('password')
        user_obj = User.objects.filter(username=username, password=md5_enc(password))
        if user_obj.exists():
            user_obj = user_obj[0]
            user_id = user_obj.id
            rep = HttpResponse(f'登录成功,用户ID:{user_id}!!')
            request.session['userid'] = user_obj.id
        else:
            rep = HttpResponse('用户名或密码错误!')
        return rep

通过CBV视图,我们可以更加清晰的分离每个接口之间不同请求的业务逻辑,对于GET请求是查询信息,POST更注重验证/更改信息

2. 为什么要as_view(),怎么实现的?为什么CBV不用带括号

看了1中对于路由的绑定,应该对于这个问题非常好奇,那么我们看看CBV父类View中as_view()的源码

django.views.View.as_view() 源码部分

    @classonlymethod
    def as_view(cls, **initkwargs):
        """Main entry point for a request-response process."""
        """ 翻译: 请求~响应过程的主入口点 """
		
        ......
        ......
		# 上面这一部分抛开不看,就是遍历initkwargs,看看传的参数会不会有问题
        
        def view(request, *args, **kwargs):  # 这里是重点,因为最后函数返回的就是view
            self = cls(**initkwargs) # 获取实例化类对象
            self.setup(request, *args, **kwargs)
            if not hasattr(self, "request"): # 这里是如果没有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) # 这里是重点,调用了dispath函数
        	# 所以我们着重去看一下dispatch函数实现了什么
		
        # 下面有一些省略,是关于文档的
        ......
        ......
        return view # 最后返回的是内部的闭包函数view
    
    
    
    def dispatch(self, request, *args, **kwargs):
        # Try to dispatch to the right method; if a method doesn't exist,
        # defer to the error handler. Also defer to the error handler if the
        # request method isn't on the approved list.
        """
        	解析: 尝试通过请求对象,分配对应的请求方法,如果方法不在http_method_names列表就报错
        """
        if request.method.lower() in self.http_method_names: # 这里是判断请求对象的方法的小写,在不在http_method_names列表
            handler = getattr(
                self, request.method.lower(), self.http_method_not_allowed
            )
            # 如果在的话,就通过getattr返回我们定义的请求类的对应方法,例如post就返回post方法
        else:
            handler = self.http_method_not_allowed
        return handler(request, *args, **kwargs) # 最后返回一个self.method方法
    
    
    
#### 
# 通过上面的源码解析,我们可以看出实际调用顺序:
as_view() -> dispatch() -> 对应的请求方法(不带括号)
所以其实就等于我们FBV中直接指定 XXX请求一样
# 所以as_view()需要带括号,因为他是一个函数,返回一个方法

3. 类视图更加强大的地方是利用Python多继承,实现Mixin类型,具体见后续文章

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值