首页 > 其他分享 >Django Swagger文档库drf-spectacular

Django Swagger文档库drf-spectacular

时间:2025-01-03 17:45:55浏览次数:1  
标签:status name spectacular drf OpenApiTypes 参数 Swagger True schema

一、概述

drf-spectacular 是一个为 Django REST Framework (DRF) 设计的 OpenAPI 3.0 和 3.1 规范的生成器。它旨在提供既理智又灵活的方式来创建 API 文档,主要实现以下三个目标:

从 DRF 中提取尽可能多的 schema 信息
提供灵活性,使 schema 在现实世界中可用(不仅仅是示例)
生成一个与最流行的客户端生成器兼容的 schema

官网:

https://drf-spectacular.readthedocs.io/en/latest/

 

先来看一个效果图吧

 用户详情

 用户更新

 接下来会详细介绍,如何实现

二、安装

环境说明

python:3.12.3

django:5.0.7

djangorestframework:3.15.2
drf-spectacular:0.28.0

 

三、配置

修改django项目中的settings.py

注册app

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'myapp',
    'drf_spectacular',  # 接口文档 swagger
    'drf_spectacular_sidecar', # 接口文档 swagger-ui
]

 

将 AutoSchema 注册到 DRF 中

最后一行添加

REST_FRAMEWORK = {
    # YOUR SETTINGS
    'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema',
}

 

修改一些默认配置

最后一行添加

# drf-spectacular  配置
SPECTACULAR_SETTINGS = {
    'TITLE': '平台的API',
    'DESCRIPTION': 'Your project description',
    'VERSION': '1.0.0',
    'SERVE_INCLUDE_SCHEMA': False,
    # OTHER SETTINGS
    'SWAGGER_UI_DIST': 'SIDECAR',  # shorthand to use the sidecar instead
    'SWAGGER_UI_FAVICON_HREF': 'SIDECAR',
    'REDOC_DIST': 'SIDECAR',
}

 

添加路由

在项目主目录的url中添加

from django.urls import path

from rest_framework.routers import DefaultRouter
from drf_spectacular.views import SpectacularAPIView, SpectacularRedocView, SpectacularSwaggerView

urlpatterns = [
    # YOUR PATTERNS
    path('doc/schema/', SpectacularAPIView.as_view(), name='schema'), # schema的配置文件的路由,下面两个ui也是根据这个配置文件来生成的
    path('doc/swagger/', SpectacularSwaggerView.as_view(url_name='schema'), name='swagger-ui'), # swagger-ui的路由
    path('doc/redoc/', SpectacularRedocView.as_view(url_name='schema'), name='redoc'), # redoc的路由
]

 

四、视图函数配置

完整视图函数如下:

from django.shortcuts import render
from rest_framework.response import Response
from rest_framework import viewsets
from rest_framework import status
from drf_spectacular.utils import extend_schema, OpenApiParameter
from drf_spectacular.types import OpenApiTypes
from django.http import JsonResponse
from django.db import transaction

from .modelsSerializers import *
from myapp.models import *
import json


@extend_schema(tags=["用户管理"])
class UserView(viewsets.ViewSet):
    @staticmethod
    def get_object(pk):
        """
        获取用户对象
        :param self:
        :param pk:
        :return:
        """
        try:
            obj = User.objects.get(pk=pk)
            return User.objects.get(pk=pk)
        except User.DoesNotExist:
            return None

    @extend_schema(
        operation_id="user-get",  # 设置右上角的名称,需要唯一性
        summary="用户列表",  # 接口上的备注 
    )
    def get(self, request, *args, **kwargs):
        """获取所有用户"""
        queryset = User.objects.all()
        serializer = UserSerializer(instance=queryset, many=True)
        return Response(data=serializer.data, status=status.HTTP_200_OK)

    @extend_schema(
        operation_id="user-post",  # 设置右上角的名称,需要唯一性
        summary="用户详情",  # 接口上的备注 
    )
    def post(self, request, pk, *args, **kwargs):
        """获取单个用户详细信息"""
        obj = self.get_object(pk=pk)
        if obj is None:
            return Response(
                {"message": "user not found"}, status=status.HTTP_404_NOT_FOUND
            )
        serializer = UserSerializer(instance=obj)
        return Response(data=serializer.data, status=status.HTTP_200_OK)

    @extend_schema(
        operation_id="user-put",  # 设置右上角的名称,需要唯一性
        summary="用户更新",  # 接口上的备注
        # 执行序列化器
        responses=UserSerializer(many=True),
        # 对参数的修改
        parameters=[
            # 这是其中一个参数
            OpenApiParameter(
                # 参数的名称是done
                name="username",
                # 对参数的备注
                description="姓名",
                # 指定参数的类型
                type=OpenApiTypes.STR,
                # 指定必须给
                required=True,
                # 指定枚举项
                # enum = [True, False],
            ),
            OpenApiParameter(
                name="account", description="账号", type=OpenApiTypes.STR, required=True
            ),
            OpenApiParameter(
                name="is_superuser",
                description="是否是超级管理员1-是;2-否",
                type=OpenApiTypes.STR,
                required=True,
                enum=[1, 2],
            ),
            OpenApiParameter(
                name="is_active",
                description="是否活动状态1-是;2-否",
                type=OpenApiTypes.STR,
                required=True,
                enum=[1, 2],
            ),
            OpenApiParameter(
                name="phone", description="手机号", type=OpenApiTypes.STR, required=True
            ),
            OpenApiParameter(
                name="email", description="邮箱", type=OpenApiTypes.STR, required=True
            ),
            
            OpenApiParameter(
                name="role",
                description="角色1-管理员,2-普通用户",
                type=OpenApiTypes.STR,
                required=True,
                enum=[1, 2],
            ),
        ],
    )
    def put(self, request, pk):
        """更新单个用户"""
        obj = self.get_object(pk=pk)
        if obj is None:
            return Response(
                {"message": "user not found"}, status=status.HTTP_404_NOT_FOUND
            )

        # 获取请求参数
        account = request.data.get("account")
        email = request.data.get("email")
        is_active = request.data.get("is_active")
        is_superuser = request.data.get("is_superuser")
        phone = request.data.get("phone")
        role = request.data.get("role")
        username = request.data.get("username")

        try:
            with transaction.atomic():  # 使用事务
                # 修改用户信息
                ret = User.objects.filter(pk=pk).update(
                    account=account,
                    email=email,
                    is_active=is_active,
                    is_superuser=is_superuser,
                    phone=phone,
                    role=role,
                    username=username,
                )
                if not ret:
                    return JsonResponse(
                        {
                            "status": status.HTTP_500_INTERNAL_SERVER_ERROR,
                            "data": [],
                            "msg": "修改用户失败",
                        },
                        status=status.HTTP_500_INTERNAL_SERVER_ERROR,
                    )

                return JsonResponse(
                    {"status": status.HTTP_200_OK, "data": []},
                    status=status.HTTP_200_OK,
                )
        except Exception as e:
            print(e)
            return JsonResponse(
                {
                    "status": status.HTTP_500_INTERNAL_SERVER_ERROR,
                    "data": [],
                    "msg": f"{e}",
                },
                status=status.HTTP_500_INTERNAL_SERVER_ERROR,
            )

    @extend_schema(
        operation_id="user-delete",  # 设置右上角的名称,需要唯一性
        summary="用户删除",  # 接口上的备注 
    )
    def delete(self, request, pk, *args, **kwargs):
        """更新单个用户"""
        obj = self.get_object(pk=pk)

        if obj is None:
            return Response(
                {"message": "user not found"}, status=status.HTTP_404_NOT_FOUND
            )
        obj.delete()

        return Response(status=status.HTTP_200_OK)

 

代码说明:

@extend_schema(tags=["用户管理"])  定义标签名,显示效果就是这里

 

def get(self, request, *args, **kwargs):
"""获取所有用户"""

注意看,3个引号部分,就是定义接口注释的,显示效果就是这里

 

@extend_schema(
operation_id="user-get", # 设置右上角的名称,需要唯一性
summary="用户列表", # 接口上的备注
)

 

注意看,summary,就是定义接口描述的,显示效果就是这里

 

@extend_schema(
        operation_id="user-put",  # 设置右上角的名称,需要唯一性
        summary="用户更新",  # 接口上的备注
        # 执行序列化器
        responses=UserSerializer(many=True),
        # 对参数的修改
        parameters=[
            # 这是其中一个参数
            OpenApiParameter(
                # 参数的名称是done
                name="username",
                # 对参数的备注
                description="姓名",
                # 指定参数的类型
                type=OpenApiTypes.STR,
                # 指定必须给
                required=True,
                # 指定枚举项
                # enum = [True, False],
            ),
            OpenApiParameter(
                name="account", description="账号", type=OpenApiTypes.STR, required=True
            ),
            OpenApiParameter(
                name="is_superuser",
                description="是否是超级管理员1-是;2-否",
                type=OpenApiTypes.STR,
                required=True,
                enum=[1, 2],
            ),
            OpenApiParameter(
                name="is_active",
                description="是否活动状态1-是;2-否",
                type=OpenApiTypes.STR,
                required=True,
                enum=[1, 2],
            ),
            OpenApiParameter(
                name="phone", description="手机号", type=OpenApiTypes.STR, required=True
            ),
            OpenApiParameter(
                name="email", description="邮箱", type=OpenApiTypes.STR, required=True
            ),
           
            OpenApiParameter(
                name="role",
                description="角色1-管理员,2-普通用户",
                type=OpenApiTypes.STR,
                required=True,
                enum=[1, 2],
            ),
        ],
    )

extend_schema,这个装饰器主要用于修改view在文档中的定义,参数意义如下:

  • operation_id:一个唯一标识ID,如果前端是使用这个接口文档生成的代码,那么这个参数将非常重要

  • parameters:添加到列表中的附加或替换参数去自动发现字段。

  • responses:修改序列化器。需要各种各样的可单独使用或组合使用的输入(有以下7种)

    • Serializer类 比如:Serializer
    • 序列化实例,比如:Serializer(many=True)
    • OpenApiTypes的基本类型或者实例 比如:OpenApiTypes.BOOL
    • OpenApiResponse类 例子见下面的备注
    • PolymorphicProxySerializer类
    • 1个字典,以状态码作为键, 以上其中一项作为值(是最常用的,格式 {200, None})
    • 1个字典,以状态码作为键,以media_type作为值 例子见下面的备注
  • request:替换序列化,接受各种输入

    • Serializer 类或者实例
    • OpenApiTypes基本类型或者实例
    • PolymorphicProxySerializer类
    • 1个字典,以media_type作为键,以上其中一项作为值
  • auth:用auth方法的显式列表替换发现的auth

  • description:替换发现的文档字符串

  • summary:一个可选的短的总结描述

  • deprecated:将操作标记为已弃用

  • tags:覆盖默认标记列表

  • exclude:设置为True以从schema中排除操作

  • operation:手动覆盖自动发现将生成的内容。你必须提供一个兼容OpenAPI3的字典,该字典可以直接翻译成YAML。

  • methods:检查extend_schema中特殊的方法,默认匹配所有

  • versions:检查extend_schema中特殊的API版本,默认匹配所有

  • example:将请求/响应示例附加到操作中

  • extensions:规范扩展

  以上这些信息,显示效果就是这里

 

这里有一个问题,始终无法解决,就是你在swagger文档页面,调试某些接口,点击Execute,请求参数都是在url里面的,无法在body里面显示。

例如,我尝试调用修改用户接口

 这里会出现500错误,提示没有username参数。因为视图函数,接收参数是从body中获取的,不是从url中获取的,所以会找不到。

 

但是如果使用postman调用,是没有任何问题的。

 

因为在extend_schema中,定义的参数,默认类型就是OpenApiParameter.QUERY,例如:

# 这是其中一个参数
            OpenApiParameter(
                # 参数的名称是done
                name="username",
                # 对参数的备注
                description="姓名",
                # 指定参数的类型
                type=OpenApiTypes.STR,
                # 指定必须给
                required=True,
                # 指定枚举项
                # enum = [True, False],
                # 参数类型
                location=OpenApiParameter.QUERY,
            ),

当指定OpenApiParameter.QUERY作为参数的位置属性时,这表示该参数将在 HTTP 请求的查询字符串中传递。例如,在一个GET请求中,查询字符串是在 URL 中?之后的部分。

 

我用chatget搜索了一下,location只有以下几种类型

1. QUERY
表示参数位于查询字符串(Query String)中。查询字符串是在 URL 中?之后的部分,通常用于GET请求传递参数。例如,在https://example.com/api/resource?param1 = value1&param2 = value2中,param1和param2的位置就是QUERY。
2. PATH
用于表示参数是路径参数(Path Parameter)。路径参数是 URL 路径的一部分,用于识别特定的资源。例如,在https://example.com/api/users/{user_id}中,{user_id}就是路径参数,它的位置属性应该设置为PATH。
3. HEADER
表示参数位于 HTTP 请求头(Header)中。请求头包含了关于请求的元数据,如Authorization(用于认证)、Content - Type(用于指定请求体的内容类型)等。
4. COOKIE
当参数位于 HTTP 请求的 Cookie 中时,使用这个位置属性。Cookie 是服务器发送给浏览器,浏览器在后续请求中回传给服务器的一小段信息,常用于用户会话管理等。

 

根据以上结果,没有body,所以这个问题,只有等官方更新升级才能解决。

 

总结一下,swagger生成的文档,只需要观看即可,某些接口不能进行直接在swagger里面调用接口。

所以调用接口,还是需要专业工具,比如:postman或者代码实现。

 

本文参考链接:https://www.cnblogs.com/guangdelw/p/18054429

 

标签:status,name,spectacular,drf,OpenApiTypes,参数,Swagger,True,schema
From: https://www.cnblogs.com/xiao987334176/p/18650349

相关文章

  • DRF之序列化器【3】数据校验
    目录前言1.基本校验2.内置和正则校验3.钩子校验4.Model校验5.保存数据之普通字段6.保存数据之FK和M2M字段7.数据校验总结总结前言在前两篇文章我们已经介绍了序列化器的序列化数据的功能以及源码实现,本文将接着介绍它的数据校验功能以及数据保存。序列化器......
  • 导出 Swagger 接口到 Excel
       importjsonimportxlwtapi_excel=xlwt.Workbook(encoding='utf-8')#创建一个文档api_sheet=api_excel.add_sheet('CRM接口')#添加一个sheetjson_file=open('D:/Test/api-docs.txt',encoding='utf-8')#打开保存的swagge......
  • DRF之序列化器【2】源码流程
    目录前言1.流程概述2.创建字段对象3.创建类4.实例化类5.序列化过程5.1UserSerializer类5.2ListSerializer类6.总结前言序列化器是Django框架中的一个重要概念,用于在Python对象和JSON等格式之间进行相互转换。通过序列化器,我们可以方便地将模型实例转换为JS......
  • 用实栗谈一谈Swagger中的SchemaFilter
    1.ISchemaFilter的作用ISchemaFilter是一个接口,主要用于拦截并修改自动生成的SwaggerSchema(在OpenAPI3.0中通常指OpenApiSchema)的定义。它能够帮助我们在以下场景中使用:为某些属性附加额外的注释或元数据在自动生成的Schema中可能会缺少一些与业务相关的描述、或......
  • Java 项目实战:全方位解析基于 Spring Boot、MySQL、FastJSON、MyBatis - Plus、Swagge
    1.引言1.1编写目的本设计文档详细阐述了SNS系统的架构、功能模块、数据结构、接口设计以及系统部署等方面,为系统的开发、测试、维护提供全面的指导,确保项目团队成员对系统有清晰一致的理解,保证系统的顺利实施与迭代优化。1.2适用范围本设计文档适用于SNS系统的开发团队、测试......
  • Java 项目实战:基于 Spring Boot、MyBatis、PageHelper、Spring Security、FastJSON、S
    一、系统概述1.1系统目标本系统的主要目标是提供一个集成化的商品管理平台,实现以下功能:高效的商品信息管理,包括商品的基本信息、类型、供应商、客户等的录入、查询、修改和删除。精确的采购流程管理,涵盖采购订单的创建、修改、查询、入库操作以及与供应商的信息关联。完善......
  • 解决 高版本SpringBoot整合Swagger 启动报错Failed to start bean ‘documentationPlu
    解决高版本SpringBoot整合Swagger启动报错Failedtostartbean‘documentationPluginsBootstrapper‘问题|Id|Title|DateAdded|SourceUrl|PostType|Body|BlogId|Description|DateUpdated|IsMarkdown|EntryName|CreatedTime|IsActive|AutoDesc|A......
  • Swagger 框架
    主要内容:1.Swagger简介2.Springfox3.Swagger的用法4.Swagger-UI的使用5.Swagger配置使用6.Swagger常用注解1.Swagger简介Swagger是一个规范和完整的框架,用于生成、描述、调用和可视化RESTful风格的Web服务。总体目标是使客户端和文件系统作为服务器以同样的......
  • MONI后台管理系统-swagger3(springdoc-openapi)集成
    springdoc-openapiJava库有助于使用SpringBoot项目自动生成API文档。springdoc-openapi通过在运行时检查应用程序来根据Spring配置、类结构和各种注释推断API语义。该库会自动生成JSON/YAML和HTML格式的页面文档。生成的文档可以使用swagger-api注释进行补......
  • SpringBoot集成Swagger3之二:Swagger3注解使用说明
    @Api:用在请求的类上,表示对类的说明  tags="说明该类的作用,可以在UI界面上看到的注解"  value="该参数没什么意义,在UI界面上也看到,所以不需要配置"@ApiOperation:用在请求的方法上,说明方法的用途、作用  value="说明方法的用途、作用"  notes="方法的备注说明"@Ap......