Django REST Framework - 使用不同序列化器类的自定义操作,空结果

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

我正在尝试定义一个自定义操作,它将使用不同的序列化器类,但我从该操作中得到一个空结果,我不确定为什么。我的操作定义代码基于 DRF 文档,但可能缺少一些东西,因为这对我来说是新的。

我有一个基于作者和书籍的简单示例来演示这一点。

这是我的视图集代码,以及我认为解决方案可能所在的操作:

class AuthorViewSet(viewsets.ModelViewSet):
    queryset = Author.objects.all()
    serializer_class = AuthorSerializer
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ['first_name', 'last_name']

    @action(detail=False, serializer_class=AuthorNoBookListSerializer)
    def no_booklist(self, request):
        serializer = self.get_serializer(data=request.data)
        if serializer.is_valid():
            return Response(serializer.data)
        else:
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

我有两个序列化器:一个包含每个作者的书籍列表,另一个没有:

class AuthorSerializer(serializers.ModelSerializer):
    book_list = serializers.ListField(source='books')

    class Meta:
        model = Author
        fields = ('id', 'first_name', 'last_name', 'book_list')

class AuthorNoBookListSerializer(serializers.ModelSerializer):
    class Meta:
        model = Author
        fields = ('id', 'first_name', 'last_name')

如果我在视图集中将

serializer_class = AuthorSerializer
替换为
serializer_class = AuthorNoBookListSerializer
,我可以看到两个序列化器都工作正常:

使用

AuthorSerializer

HTTP 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "count": 4,
    "next": null,
    "previous": null,
    "results": [
        {
            "id": 1,
            "first_name": "Ken",
            "last_name": "Kesey",
            "book_list": [
                "One Flew Over the Cuckoo's Nest"
            ]
        },
        {
            "id": 2,
            "first_name": "Brian",
            "last_name": "Kernighan",
            "book_list": [
                "The C Programming Language"
            ]
        },
        {
            "id": 3,
            "first_name": "Dennis",
            "last_name": "Ritchie",
            "book_list": [
                "The C Programming Language",
                "Lions' Commentary on UNIX: 6th Edition with Source Code"
            ]
        },
        {
            "id": 4,
            "first_name": "John",
            "last_name": "Lions",
            "book_list": [
                "Lions' Commentary on UNIX: 6th Edition with Source Code"
            ]
        }
    ]
}

与 AuthorNoBookListSerializer 一起:

HTTP 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "count": 4,
    "next": null,
    "previous": null,
    "results": [
        {
            "id": 1,
            "first_name": "Ken",
            "last_name": "Kesey"
        },
        {
            "id": 2,
            "first_name": "Brian",
            "last_name": "Kernighan"
        },
        {
            "id": 3,
            "first_name": "Dennis",
            "last_name": "Ritchie"
        },
        {
            "id": 4,
            "first_name": "John",
            "last_name": "Lions"
        }
    ]
}

但是使用该操作(在

http://localhost:8000/api/authors/no_booklist/
)我得到一个空响应:

HTTP 200 OK
Allow: GET, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{}

我认为我的动作定义有些不正确。我不确定我是否正确创建了响应。任何见解表示赞赏。

django django-rest-framework
1个回答
3
投票

正如您所说,问题不在于序列化器类。 你的问题就出在这里

@action(detail=False, serializer_class=AuthorNoBookListSerializer)

动作装饰器需要

methods
kwarg,你的问题就可以解决。

@action(methods=["get"], detail=False, serializer_class=AuthorNoBookListSerializer)

否则方法

as_view()
无法将操作映射到方法。

另一个问题是这条线

serializer = self.get_serializer(data=request.data)

序列化器仅具有来自请求的数据。由于它是一个

get
方法,我假设您没有将任何数据传递给该序列化器,因此响应时您会得到空字典。 相反,也传递查询集

     ...
     serializer = self.get_serializer(instance = self.queryset, many = True)
     # remove the validity check here
     return Response(serializer.data, status=...)
     ...

要获取分页响应,您可以在此处过滤查询集并对其进行分页。但由于它是在

super().list()
方法上实现的,所以你可以返回它。

@action(detail=False, serializer_class=AuthorNoBookListSerializer)
    def no_booklist(self, request, *args, **kwargs):
        return super().list(request, *args, **kwargs)

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