Django Rest API: How to get rid of 'UUID' in json when serializing models?

meo*_*eow 4 django django-serializer django-rest-framework

为什么“ UUID”出现在“配置文件”键值的前面,如何正确删除?

名册/serializers.py

class ShiftSerializer(serializers.ModelSerializer):

class Meta:
    model = Shift
    fields = ('id', 'profile', 'location', 'date', 'start_time', 'end_time')
Run Code Online (Sandbox Code Playgroud)

个人资料/models.py

class Profile(models.Models):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=True)
Run Code Online (Sandbox Code Playgroud)

名册/models.py

    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=True)
    profile = models.ForeignKey('profiles.Profile', null=True, blank=True)
Run Code Online (Sandbox Code Playgroud)

python manage.py shell

from roster.models import Shift
from roster.serializers import ShiftSerializer

myshift = Shift.objects.first()
serializer = ShiftSerializer(myshift)
serializer.data
Run Code Online (Sandbox Code Playgroud)

输出:

{'id': '92ca258e-8624-434a-b61d-e1cd3b80e0e8', 'profile': UUID('0081b028-0a11-47fb-971e-c47177ed93be')
Run Code Online (Sandbox Code Playgroud)

ill*_*nan 6

tl; dr

请参阅底部的解决方案

问题

.dataSerializer上的属性应仅返回对象的原始表示形式(http://www.django-rest-framework.org/api-guide/serializers/#baseserializer)。这应该通过在序列化程序和所有字段上调用to_representation()方法(http://www.django-rest-framework.org/api-guide/serializers/#to_representationself-obj)来完成。

@six.add_metaclass(SerializerMetaclass)
class Serializer(BaseSerializer):

    # ...
    # ...

    def to_representation(self, instance):
        """
        Object instance -> Dict of primitive datatypes.
        """
        # ...
        # ...

        for field in fields:

            # ...
            # ...

            if check_for_none is None:
                ret[field.field_name] = None
            else:
                ret[field.field_name] = field.to_representation(attribute)

        return ret
Run Code Online (Sandbox Code Playgroud)

来源:https : //github.com/encode/django-rest-framework/blob/master/rest_framework/serializers.py#L505-L529

具有uuid.UUID作为主键的模型存在问题。PrimaryKeyRelatedField返回uuid.UUID实例-这显然不是原始类型,导致例如UUID('')不是JSON可序列化错误。

如果未设置pk_fieldon属性,PrimaryKeyRelatedFieldto_representation方法仅返回uuid.UUID实例,请参见相关代码:

class PrimaryKeyRelatedField(RelatedField):
    # ...

    def to_representation(self, value):
        if self.pk_field is not None:
            return self.pk_field.to_representation(value.pk)
        return value.pk
Run Code Online (Sandbox Code Playgroud)

来源:https : //github.com/encode/django-rest-framework/blob/master/rest_framework/relations.py#L269-L272

为什么有问题

如其他答案和评论中所述,JSONRenderer将正确处理此问题(http://www.django-rest-framework.org/api-guide/serializers/#serializing-objects

from rest_framework.renderers import JSONRenderer

json_data = JSONRenderer().render(serializer.data)
Run Code Online (Sandbox Code Playgroud)

但是在某些情况下,您不想使用JSONRenderer

  • .data在单元测试期间进行比较;
  • 您需要存储.data在数据库中,文件,...
  • 您想.data通过发送requests到一些API:requests.post(..., json=serializer.data)
  • ...

解决方案

pk_field属性设置PrimaryKeyRelatedFieldUUIDField()

from rest_framework import serializers
from rest_framework.fields import UUIDField


class ExampleSerializer(serializers.ModelSerializer):
    id = serializers.PrimaryKeyRelatedField(required=True,
                                            allow_null=False,
                                            # This will properly serialize uuid.UUID to str:
                                            pk_field=UUIDField(format='hex_verbose'))
Run Code Online (Sandbox Code Playgroud)

并且uuid.UUID实例将str在访问时正确序列化到serializer.data


小智 1

你可以representation像这样重写

class ShiftSerializer(serializers.ModelSerializer):
    class Meta:
        model = Shift
        fields = '__all__'

    def to_representation(self, obj):
        return {
            "id": obj.id,
            "profile": obj.profile.id,
            "location": obj.location,
            "date": obj.date,
            "start_time": obj.start_time,
        }
Run Code Online (Sandbox Code Playgroud)