我想提供两种不同的序列化器,但能够从 ModelViewSet
的所有设施中受益:
- 在查看对象列表时,我希望每个对象都有一个重定向到其详细信息的URL,并且使用目标模型的
__unicode __
显示所有其他关系;
例:
{
"url": "http://127.0.0.1:8000/database/gruppi/2/",
"nome": "universitari",
"descrizione": "unitn!",
"creatore": "emilio",
"accesso": "CHI",
"membri": [
"emilio",
"michele",
"luisa",
"ivan",
"saverio"
]
}
- 查看对象的详细信息时,我想使用默认的
HyperlinkedModelSerializer
例:
{
"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/"
]
}
我设法按照以下方式完成所有这些工作:
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
以满足我的需要 . 我对这段代码并不是很满意,它看起来像是一个肮脏的黑客,最重要的是,如果两个用户在同一时刻请求列表和细节怎么办?
有没有更好的方法来实现这个 ModelViewSets
或者我是否必须使用 GenericAPIView
?
EDIT:
以下是使用自定义库 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.
}
4 回答
基于@gonz和@ user2734679的答案,我创建了this small python package,它在ModelViewset的子类中提供了这个功能 . 下面是它的工作原理 .
覆盖
get_serializer_class
方法 . 在模型mixins中使用此方法来检索正确的Serializer类 .请注意,还有一个
get_serializer
方法,它返回正确的Serializer的实例您可能会发现这个mixin很有用,它会覆盖get_serializer_class方法,并允许您声明一个将动作和序列化程序类或回退映射到通常行为的dict .
关于提供不同的序列化程序,为什么没有人选择检查HTTP方法的方法? IMO更清晰,无需额外检查 .
积分/来源:https://github.com/encode/django-rest-framework/issues/1563#issuecomment-42357718