Django Rest Framework使用相同的序列化程序以两种不同的方式序列化对象

问题描述 投票:0回答:1

[使用DRF ViewSet和APIView时,对于DurationField的序列化,我得到两个不同的结果。

在第一个端点host / app / item,它对应于视图集Items并列出了所有创建的项,我得到此响应:

[
    {
        "id": 2,
        "duration": "604800.0",
        ...
    }
    ...
]

来自host / app / user_data的响应包括与与概要文件相关的项目实例所对应的项目:

{
    ...
    "items": [
        {
            "item": {
                "id": 2,
                "duration": "P7DT00H00M00S",
                ...
            }
            ...
        }
    ]
}

但是持续时间在ISO 8601 duration format中。这非常令人困惑,因为端点使用相同的序列化器。我通过在ItemSerializer中强制使用duration = serializers.DurationField()进行序列化来确认这一点。我想要相同的格式,以秒为单位。我该怎么办?

这些是我在研究此问题时发现的问题:https://github.com/encode/django-rest-framework/issues/4430https://github.com/encode/django-rest-framework/issues/4665

网址:

router = routers.DefaultRouter()
router.register(r'items', views.Items)

urlpatterns = [
    path('', include(router.urls)),
    path('user_data', views.UserData.as_view(), name='user_data'),
    ...
]

观看次数:

class Items(viewsets.ModelViewSet):
    queryset = Item.objects.all()
    serializer_class = ItemSerializer

    def get_permissions(self):
        if self.action in ('list', 'retrieve'):
            permission_classes = [AllowAny]
        else:
            permission_classes = [IsAdminUser]
        return [permission() for permission in permission_classes]


class UserData(APIView):
    """Get authenticated user's information: data related to models User and Profile"""
    permission_classes = [IsAuthenticated]

    def get(self, request):
        user = request.user
        user_serialized = UserSerializer(user)
        profile_serialized = ProfileSerializer(user.profile)
        user_info = {}
        user_info.update(user_serialized.data)
        user_info.update(profile_serialized.data)
        return JsonResponse(user_info)

序列化器:

class ItemSerializer(serializers.ModelSerializer):
    class Meta:
        model = Item
        fields = '__all__'
        depth = 1


class ItemInstanceSerializer(serializers.ModelSerializer):
    item = ItemSerializer()

    class Meta:
        model = ItemInstance
        fields = ['item']
        depth = 2


class ProfileSerializer(serializers.ModelSerializer):
    items = ItemInstanceSerializer(source='iteminstance_set', many=True)

    class Meta:
        model = Profile
        fields = ['address', 'birth_date', 'items']

型号:

class Item(models.Model):
    ...
    SINGLE_DAY = timedelta(days=1)
    WEEK = timedelta(weeks=1)
    MONTH = timedelta(weeks=4)
    YEAR = timedelta(weeks=52)
    DURATION_CHOICES = [
        (SINGLE_DAY, 'Single-day'),
        (WEEK, 'Week'),
        (MONTH, 'Month'),
        (YEAR, 'Year'),
    ]
    duration = models.DurationField(
        choices=DURATION_CHOICES,
    )
    ...


class ItemInstance(models.Model):
    ...
    item = models.ForeignKey(
        Item,
        on_delete=models.CASCADE,
    )
    ...
django serialization django-rest-framework
1个回答
0
投票

问题出在JSONResponse中使用的UserData。它将使用Django的序列化而不是DRF的序列化。请改用rest_framework.response.Response。您可以从字面上进行更改,它应该可以工作。您也可以从item = ItemSerializer()中删除ItemInstanceSerializer行,因为ItemSerializer并没有做任何特别的事情。 DRF的默认序列化器字段很好。它们在此处由ModelSerializer隐式创建。

序列化不同的原因是serializer.data并不总是返回摘要值(完全呈现)。当您将该结构提供给JSONResponse时,它将使用非JSON友好基元的值来做自己的事情,而Response则以不同的方式来做。根据文档serializer.data should only return primitive types,但对于timedelta似乎并非如此。奇特的。

© www.soinside.com 2019 - 2024. All rights reserved.