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)