Django视图之FBV与CBV
一. CBV与FBV
CBV:Class 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/"``)`