一. 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/")
