如何在Django REST Framework序列化器中添加非数据库字段s3_url
解决Django REST Framework动态生成非模型字段的问题
你的问题核心是要给每个Drawing实例动态生成不存在于模型中的s3_url字段,根据detail字段计算得出。之前的错误在于直接把模型实例当字典操作(each['s3_url']),但Django模型实例是对象,不是字典,不能这么赋值。
下面是两种正确的实现方式:
方法一:在序列化器中用SerializerMethodField(推荐)
把序列化器里的s3_url改成SerializerMethodField,然后定义对应的获取方法,将逻辑放在序列化器里,符合职责分离原则:
class DrawingSerializer(ModelSerializer): detail = serializers.JSONField(allow_null=True) # 替换为SerializerMethodField s3_url = serializers.SerializerMethodField(read_only=True) class Meta: model = m.Drawing fields = ('id','detail','s3_url','created_at','updated_at') # 定义get_<字段名>方法,传入模型实例obj def get_s3_url(self, obj): # 调用你的detailToUrl方法,传入obj.detail计算链接 return detailToUrl(obj.detail)
视图无需额外修改,把过滤逻辑移到get_queryset更规范:
class DrawingViewSet(viewsets.ModelViewSet): queryset = m.Drawing.objects.all() serializer_class = s.DrawingSerializer def get_queryset(self): return m.Drawing.objects.filter(user=self.request.user).order_by("-id")
方法二:在视图中处理序列化后的数据
如果一定要在视图里处理,需等序列化完成后,在返回的字典数据中添加字段,而非修改模型实例:
class DrawingViewSet(viewsets.ModelViewSet): queryset = m.Drawing.objects.all() serializer_class = s.DrawingSerializer def list(self, request): queryset = m.Drawing.objects.filter(user=request.user).order_by("-id") serializer = s.DrawingSerializer(queryset, many=True) # 遍历序列化后的字典列表,添加s3_url data = serializer.data for item in data: item['s3_url'] = detailToUrl(item['detail']) return Response(data)
两种方法都能输出你想要的JSON格式,优先选第一种,因为序列化相关逻辑放在序列化器里更合理,也便于复用。
内容的提问来源于stack exchange,提问作者whitebear
相关产品推荐
相关产品推荐

