我想提供两个不同的序列化程序,同时能够从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以满足我的需要.不过,我对这段代码并不是很满意,它看起来像是肮脏的黑客攻击,最重要的是,它是what if two users request a list and a detail at the same moment?

有没有更好的方式使用ModelViewSets来实现这一点,或者我必须使用GenericAPIView来后退?

EDIT:

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方法.此方法在模型混合中用于检索正确的序列化程序类.

请注意,还有一个get_serializer方法,它返回正确序列化程序的instance

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相关问答推荐

Django项目陷入登录页面

Django ORM Groupby

Pytest-django - 测试创建和传递所需的用户对象

如何将数据库中的 None 序列化为空对象?

删除所有实例后,Django 模型实例主键不会重置为 1

如何在 PyCharm 中重命名 Django 元素?

文档中的 Mongoengine creation_time 属性

无法通过 pip 安装 Django 2.0

Django 模板列表的第一个元素

related_name 参数在 Django 模型中没有按预期工作?

django 表单为关键字参数获取了多个值

从 virtualenv 中,pip freeze > requirements.txt 给出了一堆垃圾!如何修剪它?

Django Admin:如何在同一视图中显示来自两个不同模型的字段?

Python - 覆盖 __init__ 的最干净方法,其中在 super() 调用之后必须使用可选的 kwarg?

保存前向 ModelForm 对象添加数据

Django 模型:delete() 未触发

Django 自定义用户邮箱帐户验证

ProgrammingError: 安装 Psycopg2 后,关系django_session不存在错误

用于创建和更新的基于 Django 类的视图

Django:在模块中实现 status字段的最佳方式