如何在DRF单个View中返回多个不同模型的序列化数据
实现方案
完全可以实现单接口返回多模型序列化数据,推荐直接继承APIView实现,灵活性更高,无需适配通用视图的内置规则。
前置修正
你当前的代码存在两处需要调整的点:
- 模型层的
CharField字段必须声明max_length参数,否则会触发迁移报错 - 你在
BarSerializer中声明了嵌套的FooSerializer,但Meta.fields列表未包含foo字段,且Bar模型本身未定义和Foo的关联字段,若无关联需求可以删掉该嵌套声明。
无关联模型实现方案
如果Foo和Bar两个模型没有外键关联,按如下方式实现即可:
1. 路由配置
# urls.py path("foobar/<int:foo_pk>/<int:bar_pk>/", FoobarView.as_view(), name="foobar-detail")
增加
int类型限定、路径后缀斜杠符合Django路由规范。
2. 视图实现
# views.py from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status from .models import Foo, Bar from .serializers import FooSerializer, BarSerializer class FoobarView(APIView): def get(self, request, foo_pk, bar_pk, *args, **kwargs): # 校验两个实例都存在 try: foo_obj = Foo.objects.get(pk=foo_pk) bar_obj = Bar.objects.get(pk=bar_pk) except (Foo.DoesNotExist, Bar.DoesNotExist): return Response({"detail": "请求的资源不存在"}, status=status.HTTP_404_NOT_FOUND) # 分别序列化两个实例 serialize_foo = FooSerializer(foo_obj) serialize_bar = BarSerializer(bar_obj) # 合并数据返回 return Response({ "foo": serialize_foo.data, "bar": serialize_bar.data }, status=status.HTTP_200_OK)
有关联模型简化方案
如果Bar模型定义了和Foo的外键关联,如下所示:
# models.py class Bar(models.Model): bar_title = models.CharField(max_length=100) foo = models.ForeignKey(Foo, on_delete=models.CASCADE)
那只需要调整BarSerializer的字段列表,直接用RetrieveAPIView即可实现:
# serializers.py class BarSerializer(serializers.ModelSerializer): foo = FooSerializer() class Meta: model = Bar fields = ["bar_title", "foo"] # views.py class FoobarView(generics.RetrieveAPIView): serializer_class = BarSerializer queryset = Bar.objects.all() lookup_url_kwarg = "bar_pk"
这种场景下路由中的foo_pk可以根据需求保留做参数校验,也可以直接删掉。
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

