Django休息框架,在同一个ModelViewSet中使用不同的序列化程序 [英] Django rest framework, use different serializers in the same ModelViewSet
问题描述
我想提供两个不同的序列化器,但是可以从 ModelViewSet
的所有设施中受益:
I would like to provide two different serializers and yet be able to benefit from all the facilities of ModelViewSet
:
- 当查看对象列表时,我希望每个对象具有一个重定向到其详细信息的url,并且使用
_ _ unicode _ _
目标模型;示例:
- When viewing a list of objects, I would like each object to have an url which redirects to its details and every other relation appear using
_ _ unicode _ _
of the target model; example:
[
{
"membri": [
"emilio",
"michele",
"luisa",
"ivan",
"saverio"
],
"creatore": "emilio",
"url": "http://127.0.0.1:8000/database/gruppi/2/",
"nome": "universitari",
"descrizione": "unitn!",
"accesso": "CHI"
}
]
HyperlinkedModelSerializer
,例如:HyperlinkedModelSerializer
, example:
{
"url": "http://127.0.0.1:8000/database/gruppi/2/",
"nome": "universitari",
"descrizione": "unitn!",
"creatore": "http://127.0.0.1:8000/database/utenti/3/",
"accesso": "CHI",
"membri": [
"http://127.0.0.1:8000/database/utenti/3/",
"http://127.0.0.1:8000/database/utenti/4/",
"http://127.0.0.1:8000/database/utenti/5/",
"http://127.0.0.1:8000/database/utenti/6/",
"http://127.0.0.1:8000/database/utenti/7/"
]
}
我按照以下方式设法完成所有这些工作:
I managed to make all this work as I wish in the following way:
serializers.py
# serializer to use when showing a list
class ListaGruppi(serializers.HyperlinkedModelSerializer):
membri = serializers.RelatedField(many = True)
creatore = serializers.RelatedField(many = False)
class Meta:
model = models.Gruppi
# serializer to use when showing the details
class DettaglioGruppi(serializers.HyperlinkedModelSerializer):
class Meta:
model = models.Gruppi
views.py
class DualSerializerViewSet(viewsets.ModelViewSet):
"""
ViewSet providing different serializers for list and detail views.
Use list_serializer and detail_serializer to provide them
"""
def list(self, *args, **kwargs):
self.serializer_class = self.list_serializer
return viewsets.ModelViewSet.list(self, *args, **kwargs)
def retrieve(self, *args, **kwargs):
self.serializer_class = self.detail_serializer
return viewsets.ModelViewSet.retrieve(self, *args, **kwargs)
class GruppiViewSet(DualSerializerViewSet):
model = models.Gruppi
list_serializer = serializers.ListaGruppi
detail_serializer = serializers.DettaglioGruppi
# etc.
基本上,我检测到用户正在请求列表视图或详细视图并更改 serializer_class
以满足我的需要,但我对此代码并不满意,看起来像一个肮脏的黑客,最重要的是,如果两个用户在同一时间请求一个列表和一个细节怎么办?
Basically I detect when the user is requesting a list view or a detailed view and change serializer_class
to suit my needs. I am not really satisfied with this code though, it looks like a dirty hack and, most importantly, what if two users request a list and a detail at the same moment?
有没有更好的方法来实现这个使用 ModelViewSets
或者我必须使用 GenericAPIView
?
Is there a better way to achieve this using ModelViewSets
or do I have to fall back using GenericAPIView
?
编辑:
以下是如何使用一个定制基础 ModelViewSet
:
class MultiSerializerViewSet(viewsets.ModelViewSet):
serializers = {
'default': None,
}
def get_serializer_class(self):
return self.serializers.get(self.action,
self.serializers['default'])
class GruppiViewSet(MultiSerializerViewSet):
model = models.Gruppi
serializers = {
'list': serializers.ListaGruppi,
'detail': serializers.DettaglioGruppi,
# etc.
}
推荐答案
覆盖您的 get_serializer_class
方法。您的模型mixins中使用此方法来检索正确的Serializer类。
Override your get_serializer_class
method. This method is used in your model mixins to retrieve the proper Serializer class.
请注意,还有一个 get_serializer
方法返回正确的实例 Serializer
Note that there is also a get_serializer
method which returns an instance of the correct Serializer
class DualSerializerViewSet(viewsets.ModelViewSet):
def get_serializer_class(self):
if self.action == 'list':
return serializers.ListaGruppi
if self.action == 'retrieve':
return serializers.DettaglioGruppi
return serializers.Default # I dont' know what you want for create/destroy/update.
这篇关于Django休息框架,在同一个ModelViewSet中使用不同的序列化程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!