django视图-CBV和FBV

414 阅读3分钟

视图 CBV和FBV

这是我参与8月更文挑战的第14天,活动详情查看:8月更文挑战

FBV function based view

就是在视图里使用函数处理请求

CBV class based view

就是在视图里使用类处理请求。

Python是一个面向对象的编程语言,如果只用函数来开发,有很多面向对象的优点就错失了(继承、封装、多态)。所以Django在后来加入了Class-Based-View。可以让我们用类写View。这样做的优点主要下面两种:

1.  提高了代码的复用性,可以使用面向对象的技术,比如Mixin(多继承)
1.  可以用不同的函数针对不同的HTTP方法处理,而不是通过很多if判断,提高代码可读性

1、CBV

from django.views import View
​
class xxx(View):
    
    def get(self,request):
        #专门处理get请求
        return response
    
    def post(self,request):
        #专门处理post请求 
        return response
url(r"xx/",xxx.as_view()) # 类名.as_view()执行

as_view()的流程

1. 项目运行时加载urls.py文件,执行类,as_view()方法
2. as_view()执行后,内部定义了一个view函数,并且返回.
3. 请求到来的时候,执行view函数

dispatch方法

# http_method_names = ['get'] #只允许提交的请求方法,内部执行View这个函数的时候,就会先访问这个类,这个http_method_names就会覆盖内部的这个方法
def dispatch(self, request, *args, **kwargs):
    print("dispatch执行前的操作")
    ret = super().dispatch(request, *args, **kwargs)#其实就是执行View里面内部的dispatch方法
    print("dispatch执行后的操作")
    return ret

CBV执行get和post方法前会,先执行dispatch方法

2、FBV

# views.py
def register(request):
    form_obj = RegForm()  # 获取一个空的form
    if request.method == "POST":
        form_obj = RegForm(request.POST, request.FILES)  # 获取的一个有数据的form

        if form_obj.is_valid():
            # 注册成功
            form_obj.save()  # 因为继承了ModelForm,所有可以直接保存
            return redirect("login")

    return render(request, "register.html", {"form_obj": form_obj})
url(r'^register/$', views.register, name="register"),

3、装饰器

3.1 FBV

直接加在函数上就行了

3.2 CBV

需要使用一个装饰器

from django.utils.decorators import method_decorator
method_decorator 是将函数装饰器转换成方法装饰器。

加在方法上

@method_decorator(timer)
def get(self, request):   #这样就只能get方法可以用

加在dispatch方法上

 @method_decorator(timer)  #里面的定义的请求方法都可以用
    def dispatch(self, request, *args, **kwargs):
        print("dispatch执行前的操作")
        ret = super().dispatch(request, *args, **kwargs)#其实就是执行View里面内部的dispatch方法
        print("dispatch执行后的操作")
        return ret

加在类上

@method_decorator(timer,name="get")
@method_decorator(timer,name="post")
@method_decorator(timer,name="dispatch")
class PublishersAdd(View):  #加在类上,可以指定对应的方法

自定义装饰器

装饰器:timer

# 统计时间的装饰器
import time
from functools import wraps
​
def timer(func):
    @wraps(func)
    def inner(*args, **kwargs):
        """
        inner内部函数
        """
        start = time.time()
        ret = func(*args, **kwargs)
        print("执行一共用时:{}".format(time.time() - start))
        return ret
​
    return inner
​
@timer
def func():
    """
    我是func函数
    """
    time.sleep(0.5)
    print("aaaa")
​
func()
print(func.__name__)  #打印函数名 inner (只有加 @wraps(func),才可以输出func,自己的函数名)
print(func.__doc__) #打印函数中的注释
from functools import wraps
@wraps(func) #加wraps才可以输出自己的函数,和注释,不然会输出内部函数里面的