Python笔记_57_Django视图之FBV与CBV_装饰器装饰CBV

Django视图之FBV与CBV

  • CBV:Class Based View(基于类的视图)

  • FBV:Function Based View(基于函数的视图)

FBV

我们之前写过的都是基于函数的view,就叫FBV。

from django.shortcuts import render, HttpResponse, redirect

# FBV
def login(request):
    if request.method == "GET":
        return render(request, "login.html")

    else:
        username = request.POST.get("username")
        password = request.POST.get("password")
        if username == "alex" and password == "123":
            ret = "/index/"
        else:
            ret = "/login/"
        return redirect(ret)

url.py文件中:

path("login/", views.login))
CBV

还可以把view写成基于类的,那就是CBV。
(类下的方法名称,必须是小写的)

from django.shortcuts import render, HttpResponse, redirect
from django import views

# CBV
class Login(views.View):

    def get(self, request):
        return render(request, "login.html")

    def post(self, request):
        username = request.POST.get("username")
        password = request.POST.get("password")
        if username == "alex" and password == "123":
            ret = "/index/"
        else:
            ret = "/login/"
        return redirect(ret)

urls.py文件里,写上对应的关系

path("login/", views.Login.as_view())
  • CBV视图类,执行时,会优先执行dispatch()方法(在get/post/put…方法前执行)
    base.py中的View类:
class View:
	http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
	...
	@classonlymethod
    def as_view(cls, **initkwargs):
    	...
    	def view(request, *args, **kwargs):
    		...
    		return self.dispatch(request, *args, **kwargs)
    	...
    	update_wrapper(view, cls.dispatch, assigned=())
        return 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.
       if request.method.lower() in self.http_method_names:
           handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
       else:
           handler = self.http_method_not_allowed
       return handler(request, *args, **kwargs)
   	
给视图加装饰器-使用装饰器装饰CBV

类中的方法与独立函数不完全相同,因此不能直接将函数装饰器应用于类中的方法 ,我们需要先将其转换为方法装饰器。Django中提供了method_decorator装饰器用于将函数装饰器转换为方法装饰器。

  • 定义装饰器:
import time

def wrapper(func):
    def inner(*args, **kwargs):
        start_time = time.time()
        print("start:", start_time)
        time.sleep(2)  # 睡2s是为了演示装饰器的一个效果.
        ret = func(*args, **kwargs)
        end_time = time.time()
        print("used:", end_time - start_time)
        return ret
    return inner
  • 方式一:给某个方法加上装饰器
from django.views import View
from django.utils.decorators import method_decorator

class Login(views.View):

	@method_decorator(wrapper)
    def get(self, request):
        return render(request, "login.html")

    def post(self, request):
        username = request.POST.get("username")
        password = request.POST.get("password")
        if username == "alex" and password == "123":
            ret = "/index/"
        else:
            ret = "/login/"
        return redirect(ret)
  • 方式二:加在dispatch方法上面,会给类下的所有方法加上此装饰器
class Login(views.View):

	@method_decorator(wrapper)
    def dispatch(self, request, *args, **kwargs):
        obj = super().dispatch(request, *args, **kwargs)
        return obj
        
    def get(self, request):
        return render(request, "login.html")

    def post(self, request):
        username = request.POST.get("username")
        password = request.POST.get("password")
        if username == "alex" and password == "123":
            ret = "/index/"
        else:
            ret = "/login/"
        return redirect(ret)
  • 方式三:加在类上面
    方法名称必须跟下面的方法同名(小写的请求方式).
@method_decorator(wrapper, name="get")
@method_decorator(wrapper, name="post")
class Login(views.View):
        
    def get(self, request):
        return render(request, "login.html")

    def post(self, request):
        username = request.POST.get("username")
        password = request.POST.get("password")
        if username == "alex" and password == "123":
            ret = "/index/"
        else:
            ret = "/login/"
        return redirect(ret)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值