ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
[TOC] 使用函数方式定义的视图叫函数视图,虽然使用方便,便于理解,但是当一个s视图有多种请求方式的时候,变需要使用分支来编写不同请求方式对应的逻辑。 使用函数视图,代码看上去是这样子的 ```python def my_view(request): if request.method == 'GET': return HttpResponse("get") if request.method == 'POST': return HttpResponse("post") ``` ## 1. 使用类视图 基于类的视图的核心是允许你用不同的实例方法来响应不同的HTTP请求方法,而不是在一个视图函数中使用条件分支代码来实现。 ### 创建类视图 使用类视图,代码是这样子的 ```python from django.views import View class ClassView(View): def get(self, request): return HttpResponse("get") def post(self, request): return HttpResponse("post") ``` 类视图需要继承django提供的 `View` 类,使用 `from django.views import View` 导入 ### 注册路由 配置类视图的时候,使用类视图的 `as_view` 方法注册路由 ```python urlpatterns = [ url(r'^class_view', views.ClassView.as_view(), name="class_view") ] ``` `as_view` 会返回类中一个函数的引用,它会到 `View` 中,执行 `dispatch` 方法, `dispatch` 会方法会在类中查找类似GET\POST之类的类方法,然后和请求方式进行匹配,匹配上了,就返回该函数的引用。 如果向上边的类视图发送一个 `GET` 请求,他会把 `GET` 转换为小写形式并和类中的方法进行匹配,然后匹配到 `get` 方法,会把 `get` 方法的引用返回到 `as_view` 调用处。所以在 `get` 请求下最后 `as_view` 是 `get` 函数的引用。 ## 类视图使用装饰器 可以使用装饰器为类视图增加功能,使用装饰器有三种方式。 - 在url配置中装饰 - 在类视图中装饰 - 使用Mixin扩展类 为了便于理解,使用下边的案例做演示 ```python def decorator(func): def wrapper(request, *args, **kwargs): print('装饰器被调用') return func(request, *args, **kwargs) return wrapper class ClassView(View): def get(self, request): return HttpResponse("get") def post(self, request): return HttpResponse("post") ``` ### 在url中装饰 ``` url(r'^class_view', views.decorator(views.ClassView.as_view()), name="class_view") ``` 发送 `GET` 或者 `POST` 类型请求打印结果 ``` 装饰器被调用 ``` 在url中调用该函数,并把 `as_view` 函数传入即可,这种方式会把所有被请求的函数都进行装饰。 这种方法把装饰放到了url配置中,不利于代码的完整性和可读性,所以一般情况下不使用。 ### 在类视图中装饰 在类视图中使用装饰器不能直接装饰,需要使用 `method_decorator` 把装饰器转换位适用于类的装饰器。 在我们写的装饰器中,内层函数接收的参数为 `request` ```python def decorator(func): def wrapper(request, *args, **kwargs): print('装饰器被调用') return func(request, *args, **kwargs) return wrapper ``` 而在类视图的函数中,第一个参数是 `self` ,所以要使用 `method_decorator` 把装饰器的第一个参数补充为 `self` 以使用类视图中的函数。 也可以手动为装饰器添加参数 `self` ```python def decorator(func): def wrapper(self, request, *args, **kwargs): print('装饰器被调用') return func(self, request, *args, **kwargs) return wrapper ``` #### 装饰所有函数 可以重写并装饰类的 `dispatch` 函数,代码如下 ```python class ClassView(View): @method_decorator(decorator) def dispatch(self, request, *args, **kwargs): return super().dispatch(request, *args, **kwargs) def get(self, request): return HttpResponse("get") def post(self, request): return HttpResponse("post") ``` 使用 `GET` 或者 `POST` 方式请求,都会执行装饰器,打印结果 ``` 装饰器被调用 ``` #### 只装饰某一个函数 ```python class ClassView(View): @method_decorator(decorator) def get(self, request): return HttpResponse("get") def post(self, request): return HttpResponse("post") ``` 只有使用 `GET` 方式请求,才会执行装饰器,打印结果 ``` 装饰器被调用 ``` `POST` 方式不会执行装饰器。 ### method_decorator 的 name 参数 装饰全部函数 ```python @method_decorator(decorator, name="dispatch") class ClassView(View): def get(self, request): return HttpResponse("get") def post(self, request): return HttpResponse("post") ``` 指定被装饰的函数 ```python @method_decorator(decorator, name="get") class ClassView(View): def get(self, request): return HttpResponse("get") def post(self, request): return HttpResponse("post") ``` ## 使用Mixin扩展类 扩展类使用了 Python 多继承的 `MRO` 特性。 ``` class MyMixin(object): @classmethod def as_view(cls, *args, **kwargs): view = super().as_view(*args, **kwargs) view = decorator(view) return view class ClassView(MyMixin, View): def get(self, request): return HttpResponse("get") def post(self, request): return HttpResponse("post") ``` 这种方式会装饰所有函数,可以使用这种方式为函数添加多个装饰器。