Bla*_*ear 165 django serialization django-rest-framework
我想提供两种不同的序列化器,但能够从以下所有设施中受益ModelViewSet
:
__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"
]
}
Run Code Online (Sandbox Code Playgroud)
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/"
]
}
Run Code Online (Sandbox Code Playgroud)
我设法按照以下方式完成所有这些工作:
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
Run Code Online (Sandbox Code Playgroud)
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.
Run Code Online (Sandbox Code Playgroud)
基本上我检测用户何时请求列表视图或详细视图并serializer_class
根据我的需要进行更改.我对这段代码并不是很满意,它看起来像是一个肮脏的黑客,最重要的是,如果两个用户同时请求列表和细节怎么办?
是否有更好的方法来实现这一目标ModelViewSets
或者我是否必须使用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.
}
Run Code Online (Sandbox Code Playgroud)
use*_*688 251
覆盖您的get_serializer_class
方法.在模型mixins中使用此方法来检索正确的Serializer类.
请注意,还有一个get_serializer
方法可以返回正确的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.
Run Code Online (Sandbox Code Playgroud)
gon*_*onz 81
您可能会发现这个mixin很有用,它会覆盖get_serializer_class方法并允许您声明一个将动作和序列化程序类或回退映射到通常行为的dict.
class MultiSerializerViewSetMixin(object):
def get_serializer_class(self):
"""
Look for serializer class in self.serializer_action_classes, which
should be a dict mapping action name (key) to serializer class (value),
i.e.:
class MyViewSet(MultiSerializerViewSetMixin, ViewSet):
serializer_class = MyDefaultSerializer
serializer_action_classes = {
'list': MyListSerializer,
'my_action': MyActionSerializer,
}
@action
def my_action:
...
If there's no entry for that action then just fallback to the regular
get_serializer_class lookup: self.serializer_class, DefaultSerializer.
"""
try:
return self.serializer_action_classes[self.action]
except (KeyError, AttributeError):
return super(MultiSerializerViewSetMixin, self).get_serializer_class()
Run Code Online (Sandbox Code Playgroud)
小智 11
只是想添加到现有的解决方案中。如果您想要为视图集的额外操作使用不同的序列化器(即使用@action
装饰器),您可以在装饰器中添加 kwargs,如下所示:
@action(methods=['POST'], serializer_class=YourSpecialSerializer)
def your_extra_action(self, request):
serializer = self.get_serializer(data=request.data)
...
Run Code Online (Sandbox Code Playgroud)
基于@gonz和@ user2734679的答案,我创建了这个小的python包,它提供了这个功能,形成了ModelViewset 的子类.下面是它的工作原理.
from drf_custom_viewsets.viewsets.CustomSerializerViewSet
from myapp.serializers import DefaltSerializer, CustomSerializer1, CustomSerializer2
class MyViewSet(CustomSerializerViewSet):
serializer_class = DefaultSerializer
custom_serializer_classes = {
'create': CustomSerializer1,
'update': CustomSerializer2,
}
Run Code Online (Sandbox Code Playgroud)
关于提供不同的序列化器,为什么没人去检查HTTP方法呢?IMO更加清晰,不需要额外的检查。
def get_serializer_class(self):
if self.request.method == 'POST':
return NewRackItemSerializer
return RackItemSerializer
Run Code Online (Sandbox Code Playgroud)
积分/来源:https : //github.com/encode/django-rest-framework/issues/1563#issuecomment-42357718
This answer is the same as the accepted answer but I prefer to do in this way.
Returns the class that should be used for the serializer. Defaults to returning the
serializer_class
attribute.May be overridden to provide dynamic behavior, such as using different serializers for reading and write operations or providing different serializers to the different types of users. the serializer_class attribute.
class DualSerializerViewSet(viewsets.ModelViewSet):
# mapping serializer into the action
serializer_classes = {
'list': serializers.ListaGruppi,
'retrieve': serializers.DettaglioGruppi,
# ... other actions
}
default_serializer_class = DefaultSerializer # Your default serializer
def get_serializer_class(self):
return self.serializer_classes.get(self.action, self.default_serializer_class)
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
57908 次 |
最近记录: |