Django视图之FBV与CBV
一. CBV与FBV
CBV:Class Based View
FBV:Function Based View
我们之前写过的都是基于函数的view,就叫FBV。还可以把view写成基于类的,那就是CBV。
下面我们就以前面所写的图书管理系统中的添加出版社为例:
FBV版本:
# 新增出版社 def add_publisher(request): if request.method == "POST": pub_name = request.POST.get("name") models.Publisher.objects.create(name=pub_name) return redirect("/publisher_list/") return render(request, "add_publisher.html")
CBV版本:
from django.views import View class AddPublisher(View): def get(self, request): return render(request, "add_publisher.html") def post(self, request): pub_name = request.POST.get("name") models.Publisher.objects.create(name=pub_name) return redirect("/publisher_list/")
注意:使用CBV时,urls.py中也做对应的修改:
path('add_publisher/', views.AddPublisher.as_view()), # 新增出版社
二. 给视图加装饰器
1. 使用装饰器装饰FBV
FBV本身就是一个函数,所以和给普通的函数加装饰器无差:
def wrapper(func): def inner(*args, **kwargs): start_time = time.time() ret = func(*args, **kwargs) end_time = time.time() print("used:", end_time - start_time) return ret return inner # 新增出版社 @wrapper def add_publisher(request): if request.method == "POST": pub_name = request.POST.get("name") models.Publisher.objects.create(name=pub_name) return redirect("/publisher_list/") return render(request, "add_publisher.html")
2. 使用装饰器装饰CBV
类中的方法与独立函数不完全相同,因此不能直接将函数装饰器应用于类中的方法 ,我们需要先将其转换为方法装饰器。Django中提供了method_decorator装饰器用于将函数装饰器转换为方法装饰器。
方式一:给某个方法加上装饰器(此例给get方法加上)
from django.views import View from django.utils.decorators import method_decorator class AddPublisher(View): # CBV版 @method_decorator(wrapper) def get(self, request): return render(request, "add_publisher.html") def post(self, request): pub_name = request.POST.get("name") models.Publisher.objects.create(name=pub_name) return redirect("/publisher_list/")
方式二:加在dispatch方法上面,会给类下的所有方法加上此装饰器
class AddPublisher(View): # CBV版 @method_decorator(wrapper) def dispatch(self, request, *args, **kwargs): obj = super(AddPublisher, self).dispatch(request, *args, **kwargs) return obj def get(self, request): return render(request, "add_publisher.html") def post(self, request): pub_name = request.POST.get("name") models.Publisher.objects.create(name=pub_name) return redirect("/publisher_list/")
方式三:加在类上面
@method_decorator(wrapper, name="post") @method_decorator(wrapper, name="get") # 给哪个方法加,就要指定name class AddPublisher(View): # CBV版 def dispatch(self, request, *args, **kwargs): obj = super(AddPublisher, self).dispatch(request, *args, **kwargs) return obj def get(self, request): return render(request, "add_publisher.html") def post(self, request): pub_name = request.POST.get("name") models.Publisher.objects.create(name=pub_name) return redirect("/publisher_list/")