You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django REST Framework中Serializer的to_representation方法报错排查

问题分析:Django REST Framework Serializer覆写create后to_representation报错

问题背景

将原本正常工作的ModelSerializer改为serializers.Serializer并覆写create方法后,TestModel对象能成功存入数据库,但调用serializer.data时触发to_representation报错。

Serializer代码

class AdddTestModel(serializers.Serializer):
    name = serializers.CharField()
    score = serializers.FloatField()
    score2 = serializers.FloatField()
    song = serializers.IntegerField()

    def create(self, validated_data):
        print(validated_data["song"])
        song = Song.objects.get(id=validated_data["song"])
        print(song)
        instance = TestModel.objects.create(name=validated_data["name"], score = validated_data["score"], score2 = validated_data["score2"], song = song)
        return instance

    def to_representation(self, instance):
        representation = super().to_representation(instance)
        return representation

视图代码

@api_view(["POST"])
def addTestModel(request):
    serializer = AdddTestModel(data=request.data)
    if serializer.is_valid():
        serializer.save()
        
        print(serializer.data)
        return Response("hello", status=status.HTTP_201_CREATED)
    return Response("Error", status=status.HTTP_401_UNAUTHORIZED)

报错信息

Internal Server Error: /api/addTest/
Traceback (most recent call last):
  File "C:\Users\thoma\Documents\venv\lib\site-packages\django\core\handlers\exception.py", line 55, in inner
    response = get_response(request)
  File "C:\Users\thoma\Documents\venv\lib\site-packages\django\core\handlers\base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Users\thoma\Documents\venv\lib\site-packages\django\views\decorators\csrf.py", line 56, in wrapper_view
    return view_func(*args, **kwargs)
  File "C:\Users\thoma\Documents\venv\lib\site-packages\django\views\generic\base.py", line 104, in view
    return self.dispatch(request, *args, **kwargs)
  File "C:\Users\thoma\Documents\venv\lib\site-packages\rest_framework\views.py", line 509, in dispatch
    response = self.handle_exception(exc)
  File "C:\Users\thoma\Documents\venv\lib\site-packages\rest_framework\views.py", line 469, in handle_exception
    self.raise_uncaught_exception(exc)
  File "C:\Users\thoma\Documents\venv\lib\site-packages\rest_framework\views.py", line 480, in raise_uncaught_exception
    raise exc
  File "C:\Users\thoma\Documents\venv\lib\site-packages\rest_framework\views.py", line 506, in dispatch
    response = handler(request, *args, **kwargs)
  File "C:\Users\thoma\Documents\venv\lib\site-packages\rest_framework\decorators.py", line 50, in handler
    return func(*args, **kwargs)
  File "C:\Users\thoma\Documents\realestate\theFirstView\api\views.py", line 53, in addTestModel
    print(serializer.data)
  File "C:\Users\thoma\Documents\venv\lib\site-packages\rest_framework\serializers.py", line 555, in data
    ret = super().data
  File "C:\Users\thoma\Documents\venv\lib\site-packages\rest_framework\serializers.py", line 253, in data
    self._data = self.to_representation(self.instance)
  File "C:\Users\thoma\Documents\venv\lib\site-packages\rest_framework\serializers.py", line 522, in to_representation
    ret[field.field_name] = field.to_representation(attribute)
  File "C:\Users\thoma\Documents\venv\lib\site-packages\rest_framework\fields.py", line 915, in to_representation
    return int(value)
TypeError: int() argument must be a string, a bytes-like object or a real number, not 'Song'

原因解析

  • ModelSerializer的自动适配:ModelSerializer会根据模型字段类型自动匹配序列化字段。比如TestModel中的song是外键,ModelSerializer会自动使用PrimaryKeyRelatedField,该字段在反序列化时能把传入的ID转为Song实例,序列化时会自动提取实例ID作为返回值,因此不会出现类型错误。
  • Serializer的手动字段缺陷:手动将song定义为IntegerField后,该字段仅能在反序列化阶段处理数值型ID,但序列化阶段(生成serializer.data)会尝试直接将TestModel实例中的song字段(实际是Song模型对象)转成int,而IntegerField的to_representation方法无法处理模型对象,因此抛出TypeError。

解决方案

方案1:使用PrimaryKeyRelatedField替换IntegerField

替换字段类型后,它会自动处理序列化/反序列化的类型转换,同时简化create方法代码:

class AdddTestModel(serializers.Serializer):
    name = serializers.CharField()
    score = serializers.FloatField()
    score2 = serializers.FloatField()
    song = serializers.PrimaryKeyRelatedField(queryset=Song.objects.all())

    def create(self, validated_data):
        # validated_data["song"]已自动转为Song实例,无需手动查询
        instance = TestModel.objects.create(**validated_data)
        return instance

方案2:手动在to_representation中处理song字段

若坚持使用IntegerField,可在序列化阶段手动将Song对象转为ID:

def to_representation(self, instance):
    representation = super().to_representation(instance)
    # 将Song对象替换为对应ID
    representation['song'] = instance.song.id
    return representation

内容的提问来源于stack exchange,提问作者Thomas Michaelides

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 14:25:59