使用drf-spectacular时如何让Swagger示例区展示主键id字段
问题原因
DRF的ModelSerializer默认会将模型主键id标记为只读字段,drf-spectacular生成OpenAPI Schema时,请求体示例默认仅包含可写字段,因此id不会出现在Swagger的请求示例区域。
最优解决方案
方案1:直接修改序列化器字段属性(适合序列化器仅用于写操作/确实需要接收id参数的场景)
直接在序列化器中显式设置id为可写字段即可,drf-spectacular会自动将其加入请求示例:
# Serializers.py class SerializerExample(serializers.ModelSerializer): class Meta: model = Book fields = ('id','name') # 新增这段配置,将id设为可写 extra_kwargs = { 'id': {'read_only': False} }
方案2:继承原有序列化器创建专用子类(适合原序列化器其他场景需要id为只读的场景)
不用修改原有序列化器逻辑,仅为当前批量更新接口创建一个子类继承原序列化器,仅修改id的只读属性,后续原序列化器新增/修改字段会自动同步到子类,无需重复维护:
# Serializers.py # 原有序列化器保持不变,其他接口继续使用 class SerializerExample(serializers.ModelSerializer): class Meta: model = Book fields = ('id','name') # 新增批量更新专用子类 class SerializerExampleForBulkUpdate(SerializerExample): class Meta(SerializerExample.Meta): extra_kwargs = { 'id': {'read_only': False} }
视图中修改extend_schema的request参数即可:
# Views.py class BooksBulkUpdate(APIView): @extend_schema( request=SerializerExampleForBulkUpdate(many=True), responses={200:''}, ) def put(self, request, format=None): # 原有逻辑不变 with transaction.atomic(): for data in request.data: book = Book.objects.get(pk=data['id']) serializer = SerializerExample(book, data=data, partial=True) if serializer.is_valid(): serializer.save() else: return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) return Response()
方案3:直接指定自定义示例(适合不想修改序列化器的场景)
无需改动序列化器逻辑,直接在extend_schema中显式指定请求示例:
# Views.py from drf_spectacular.utils import extend_schema, OpenApiExample class BooksBulkUpdate(APIView): @extend_schema( request=SerializerExample(many=True), responses={200:''}, examples=[ OpenApiExample( '批量更新书籍示例', value=[ {'id': 1, 'name': '新书名1'}, {'id': 2, 'name': '新书名2'} ], request_only=True, ) ] ) def put(self, request, format=None): # 原有逻辑不变 with transaction.atomic(): for data in request.data: book = Book.objects.get(pk=data['id']) serializer = SerializerExample(book, data=data, partial=True) if serializer.is_valid(): serializer.save() else: return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) return Response()
内容的提问来源于stack exchange,提问作者David1212k
相关产品推荐
相关产品推荐

