如何在CBV中使用装饰器

本文介绍了装饰器的基本概念,强调其在Django Class-Based Views (CBV) 中的应用。详细讨论了如何在路由层和视图层使用装饰器,包括在类方法上单独或批量应用装饰器,并提供了Django内置装饰器如`login_required`、`permission_required`、`cache_page`等的使用示例。

1 装饰器简介

概念:本质上是一个python闭包函数,可以让其他函数在不需要做任何代码的变动的前提下增加额外的功能;返回值也是函数的对象,

作用:提高代码重复利用率,缩减代码量,同时也有助于代码的可读性和可维护性

应用场景:
1 计算某个函数的运行时间和运行次数(通过在外层函数加上时间计算函数或运算次数统计函数)
2 框架的路由传参()
3 函数的运行日志(插入日志)
4 多个函数实现事务处理的一致性(让函数一起成功运行,或一起运行失败)
5 缓存(实现缓存处理)
6 权限校验(在函数外层套上权限验证的代码,实现权限校验)

2 CBV的装饰器使用

1 在路由层使用装饰器

在视图入口处,即路由分发的过程中使用

通过as_view(),类会被转换成视图函数。在转换好的视图函数上直接使用装饰器函数

from django.contrib.auth.decorators import login_required, permission_required
from django.views.generic import TemplateView
from .views import VoteView

urlpatterns = [
    path('about/', login_required(TemplateView.as_view(template_name="secret.html"))),
    path('vote/', permission_required('polls.can_vote')(VoteView.as_view())),
]

此方法会为该类的所有的方法加上装饰器,而不能为单个方法添加

2 在视图层中使用装饰器

使用 method_decorator 方法将其转换为适用于类视图方法的装饰器

2.1 同时添加多个装饰器

method_decorator方法支持同时添加多个装饰器,先将要用的装饰器放在一个元祖或list中

decorators = [never_cache, login_required]

@method_decorator(decorators, name='dispatch')
class ProtectedView(TemplateView):
    template_name = 'secret.html'

@method_decorator(never_cache, name='dispatch')
@method_decorator(login_required, name='dispatch')
class ProtectedView(TemplateView):
    template_name = 'secret.html'

2.3 在类中的方法上添加装饰器

不用指定name值,name值默认为空

from django.contrib.auth.decorators import login_required
from django.views import View
from django.utils.decorators import method_decorator

class Order(View):
    @method_decorator(login_required)
    def get(self, request):
        return render(request, 'order.html')

2.4 直接在类上添加装饰器

必须把方法名称作为参数给到name

2.4.1 单独为类中的函数添加装饰器

name属性只支撑一个对象,当需要为多个方法使用同一个装饰器时,需要重复添加

@method_decorator(login_required, name='post')
@method_decorator(login_required, name="get")
class Logout(View):
    def get(self, request):
        auth.logout(request)
        return redirect('/login_c/')
    def post(self, request):
        return redirect('/cheeck/')
2.4.2 为类中的所有函数添加装饰器

将name设为dispatch,dispatch内部通过反射来实现函数执行

@method_decorator(login_required, name="dispatch")
class Logout(View):
    def get(self, request):
        auth.logout(request)
        return redirect('/login_c/')
    def post(self, request):
        return redirect('/cheeck/')

在Django 1.9之前,不能对类使用method_decorator,必须重写dispatch方法;

在Django 1.9版本,有内部定义dispatch方法

Django 1.9 前版本

from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from django.views.generic import TemplateView

class ProtectedView(TemplateView):
    template_name = 'secret.html'
	
    @method_decorator(login_required)
    def dispatch(self, *args, **kwargs):
        return super().dispatch(*args, **kwargs)

Django 1.9及以后版本

@method_decorator(login_required, name='dispatch')
class ProtectedView(TemplateView):
    template_name = 'secret.html'

method_decorator方法会对收到的被装饰对象进行判断:

​ 如果是方法,继续进行装饰;如果是类,需要调取name值作为实际被装饰对象。所以在类中使用时,需要把方法名给name

3 Django装饰器方法

3.1 自定义函数

def login(request):
    if request.method == "GET":
        return render   (request, "login.html")
    else:
        username = request.POST.get('username')
        password = request.POST.get('password')
        user_obj = auth.authenticate(username=username, password=password)
        if user_obj:
            auth.login(request, user_obj)
            path = request.GET.get('next') or '/index/'
            return redirect(path)
        return redirect('/login/')

3.2 Django内置装饰器简单介绍(常用)

3.2.1 auth模块
login_required 方法

登录验证(通过session key检查是否登录),验证通过后可征程执行请求,验证失败后记录当前请求地址并跳转登录页面,在登录成功后跳转已经记录好下来的请求地址
全局设置中后设置登录验证后跳转地址:

LOGIN_URL = '/accounts/login/'

需要在setting中重新定义:

LOGIN_URL = '/login/'
permission_required 方法

权限验证(通过数据库中的auth_permission数据表检查),权限能约束用户行为,当业务逻辑中涉及到权限检查时

3.2.2 cache 模块
cache_page 方法

对页面进行缓存(可在参数中定义过期时间)

cache_control 方法

控制缓存

私有缓存数据(用户浏览器)和公有缓存数据(提供者),需要一个方法告诉缓存那些数据是私有的,那些是可以共享的

never_cache方法

禁用缓存,节省存储空间

3.2.3 http 模块

Django框架在进行路由分发时,不管是FBV还是CBV,完全依赖于用户请求的URL,不考虑请求所使用的HTTP方法。
也就是说,对同一个URL使用不同的HTTP方法,都将由同一个视图函数处理。

require_http_methods 方法

通过这个函数设定只允许的请求方法,从而拦截不允许的请求方法并在拦截后返回405错误,参数为列表形式

基于require_http_methods方法,有三个可直接使用的方法
require_GET() 只支持GET请求
require_POST() 只支持POST请求
require_SAFE() 只支持GET和HEAD请求

3.2.4 csrf 模块

局部设置防跨站请求伪造功能(全局用中间件)

def csrf_exempt 方法

标识一个视图可以被跨域访问,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件

csrf_protect 方法

为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件

<think>我们使用drf-yasg库中的@swagger_auto_schema装饰器来自定义API接口文档。该装饰器可以应用于视图函数或视图类的方法上,以覆盖自动生成的OpenAPI文档属性。 以下是一些常见的自定义场景和用法: ### 1. 基本用法 ```python from drf_yasg.utils import swagger_auto_schema from rest_framework.response import Response from rest_framework.views import APIView class UserListView(APIView): @swagger_auto_schema( operation_summary="获取用户列表", operation_description="这个接口用于获取系统中的所有用户信息。", responses={200: '返回用户列表数据'} ) def get(self, request): # 视图逻辑 return Response(...) ``` ### 2. 指定请求体和响应体 使用`request_body`和`responses`参数来指定请求和响应的序列化器。 ```python from .serializers import UserCreateSerializer, UserSerializer class UserCreateView(APIView): @swagger_auto_schema( request_body=UserCreateSerializer, responses={201: UserSerializer}, operation_summary="创建用户" ) def post(self, request): # 创建用户的逻辑 return Response(...) ``` ### 3. 为视图集的不同方法自定义 在视图集(ViewSet)中,我们可以为不同的HTTP方法分别指定装饰器。 ```python from rest_framework.viewsets import ModelViewSet from .models import User from .serializers import UserSerializer class UserViewSet(ModelViewSet): queryset = User.objects.all() serializer_class = UserSerializer @swagger_auto_schema( operation_summary="部分更新用户信息", request_body=UserSerializer, # 注意:部分更新通常使用partial=True,但序列化器可能相同 responses={200: UserSerializer} ) def partial_update(self, request, *args, **kwargs): return super().partial_update(request, *args, **kwargs) ``` ### 4. 为基于函数的视图(FBV)自定义 ```python from rest_framework.decorators import api_view from drf_yasg.utils import swagger_auto_schema @api_view(['POST']) @swagger_auto_schema( operation_summary="用户登录", request_body=openapi.Schema( type=openapi.TYPE_OBJECT, properties={ 'username': openapi.Schema(type=openapi.TYPE_STRING), 'password': openapi.Schema(type=openapi.TYPE_STRING), }, required=['username', 'password'] ), responses={200: '登录成功', 400: '无效输入'} ) def user_login(request): # 登录逻辑 ... ``` ### 5. 手动指定参数 使用`manual_parameters`参数可以添加、修改接口的参数描述。 ```python class UserSearchView(APIView): @swagger_auto_schema( manual_parameters=[ openapi.Parameter( 'username', openapi.IN_QUERY, description="按用户名搜索", type=openapi.TYPE_STRING ), openapi.Parameter( 'email', openapi.IN_QUERY, description="按邮箱搜索", type=openapi.TYPE_STRING ) ], operation_summary="搜索用户" ) def get(self, request): # 搜索逻辑 ... ``` ### 6. 使用 openapi.Schema 自定义复杂结构 当序列化器无法满足描述需求时,可以直接使用`openapi.Schema`来定义数据结构。 ```python @swagger_auto_schema( responses={ 200: openapi.Schema( type=openapi.TYPE_OBJECT, properties={ 'count': openapi.Schema(type=openapi.TYPE_INTEGER), 'results': openapi.Schema( type=openapi.TYPE_ARRAY, items=openapi.Items(type=openapi.TYPE_STRING) # 或者用Schema定义复杂对象 ) } ) } ) def custom_response_view(request): # 返回自定义结构的响应 ... ``` ### 7. 排除某些方法 如果不想为某个方法生成文档,可以设置`auto_schema=None`。 ```python class UserListView(APIView): @swagger_auto_schema(auto_schema=None) def get(self, request): # 这个方法将不会出现在Swagger文档中 ... ``` ### 8. 使用`method`和`methods`参数 对于基于函数的视图,如果支持多个HTTP方法,可以使用`method`(单个方法)或`methods`(多个方法)参数来指定装饰器应用的方法。 ```python @api_view(['GET', 'POST']) @swagger_auto_schema(method='get', operation_summary="获取用户") @swagger_auto_schema(method='post', request_body=UserCreateSerializer, operation_summary="创建用户") def user_list(request): if request.method == 'GET': ... elif request.method == 'POST': ... ``` ### 9. 标记接口为已弃用 使用`deprecated=True`参数。 ```python @swagger_auto_schema(deprecated=True, ...) ``` ### 10. 设置标签(Tag) 使用`tags`参数可以将接口分组到指定的标签下。 ```python @swagger_auto_schema(tags=['用户管理'], ...) ``` ### 注意事项 - 使用`@swagger_auto_schema`时,确保将其放在视图装饰器(如`@api_view`)的下面,这样它才能正确覆盖自动生成的文档。 - 对于视图集,如果要为默认的方法(如`list`, `create`等)添加装饰器,可以直接在类中重写这些方法并添加装饰器,或者使用`@action`装饰器的`swagger_auto_schema`参数。 通过以上方式,您可以根据需要灵活地自定义每个API接口的文档。 §§相关问题§§ 1. 如何在 Swagger 中为嵌套序列化器生成正确的文档结构? 2. 如何为 Django REST Framework 的基于类的视图(CBV)中的特定方法(如 create, update)自定义 Swagger 文档? 3. 如何为使用了分页(Pagination)的列表接口自定义 Swagger 文档中的分页参数和响应结构?</think>### 使用 `@swagger_auto_schema` 自定义 Swagger API 文档 在 Django使用 `drf-yasg` 的 `@swagger_auto_schema` 装饰器可以精细控制 API 文档的生成。以下是核心用法和示例: #### 一、基础用法 ```python from drf_yasg.utils import swagger_auto_schema from rest_framework.views import APIView class UserAPI(APIView): @swagger_auto_schema( operation_summary="用户列表", # 接口标题 operation_description="获取系统中所有用户信息", # 详细描述 responses={200: "获取成功", 404: "数据不存在"} # 响应状态码 ) def get(self, request): # 视图逻辑 ``` #### 二、自定义请求/响应结构 ```python from .serializers import UserSerializer @swagger_auto_schema( method='post', request_body=UserSerializer, # 请求体结构 responses={ 201: UserSerializer, # 成功响应结构 400: "无效输入" } ) @api_view(['POST']) def create_user(request): # 创建用户逻辑 ``` #### 三、参数定制 ```python from drf_yasg import openapi @swagger_auto_schema( manual_parameters=[ openapi.Parameter( 'username', # 参数名 openapi.IN_QUERY, # 参数位置 description="按用户名过滤", type=openapi.TYPE_STRING ), openapi.Parameter( 'is_active', openapi.IN_QUERY, description="激活状态过滤", type=openapi.TYPE_BOOLEAN ) ] ) def get(self, request): # 带过滤参数的GET请求 ``` #### 四、高级用法 1. **覆盖自动生成字段**: ```python @swagger_auto_schema( operation_id="custom_user_detail", tags=["用户管理"], # 自定义分组标签 deprecated=True # 标记为弃用接口 ) ``` 2. **自定义响应示例**: ```python responses={ 200: openapi.Response( description="成功响应", examples={ "application/json": { "id": 1, "name": "张三", "email": "zhangsan@example.com" } } ) } ``` 3. **忽略特定字段**: ```python @swagger_auto_schema( ignore_params=['internal_id'] # 隐藏内部字段 ) ``` #### 五、完整示例 ```python from drf_yasg import openapi from drf_yasg.utils import swagger_auto_schema class OrderAPI(APIView): @swagger_auto_schema( operation_summary="创建订单", operation_description="需要用户认证令牌", manual_parameters=[ openapi.Parameter( 'Authorization', openapi.IN_HEADER, description="JWT Token", type=openapi.TYPE_STRING, default="Bearer <token>" ) ], request_body=OrderSerializer, responses={ 201: OrderSerializer, 400: "无效输入", 401: "未授权" } ) def post(self, request): # 订单创建逻辑 return Response(...) ``` #### 六、调试技巧 1. 使用 `auto_schema=None` 完全禁用自动生成: ```python @swagger_auto_schema(auto_schema=None) def hidden_api(request): # 不会出现在文档中 ``` 2. 查看原始 OpenAPI 定义: ``` http://localhost:8000/swagger.json ``` > **最佳实践**: > 1. 对关键业务接口使用 `operation_description` 添加详细文档[^2] > 2. 使用 `responses` 明确定义所有可能的返回状态[^1] > 3. 通过 `tags` 对接口进行业务分组[^4] > 4. 生产环境应结合 `SECURITY_DEFINITIONS` 配置认证[^5]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值