一尘不染

Django rest框架,在同一ModelViewSet中使用不同的序列化器

django

我想提供两个不同的序列化器,但仍然可以从以下所有功能中受益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

编辑:
这是使用自定义库的方法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.
    }

阅读 738

收藏
2020-03-26

共1个答案

一尘不染

覆盖你的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.    
2020-03-26