我正在尝试定义一个自定义操作,它将使用不同的序列化器类,但我从该操作中得到一个空结果,我不确定为什么。我的操作定义代码基于 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
{}
我认为我的动作定义有些不正确。我不确定我是否正确创建了响应。任何见解表示赞赏。
正如您所说,问题不在于序列化器类。 你的问题就出在这里
@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)