DRF中的高级序列化

时间:2015-07-31 07:31:01

标签: django django-rest-framework

我正在尝试使用Django Rest Framework实现某些功能。 这个想法是让一个模型在只读中有几个类型的几个字段,并且具有可供用户写入的相同字段,这些字段在提供数据时优先。 由于这不应该非常清楚,例如:

该模型将是:

class Site(models.Model):
    title = models.CharField(_('Title'),max_length=300)
    title_modified = models.CharField(_('Title'),max_length=300)

要定义的视图集:

class SiteViewSet(viewsets.ModelViewSet):
   serializer_class = SiteSerializer
   queryset = Site.objects.all()

序列化器:

class SiteSerializer(serializers.ModelSerializer):
    class Meta:
        model = Site
        depth = 1

我想要做的是只能向客户端提供“标题”数据,但如果title_modified为空,则标题将具有title字段,如果title_modified字段不为空,则标题将具有title_modified字段。 同样的想法,当客户端写入标题时,我希望我的服务器将数据写入title_modified,并始终保持标题信息不变。

我不知道如何以足够通用的方式实现这一点,以适用于所有类型的领域。 我认为在序列化/反序列化上只需要一些魔法,但我似乎无法找到它。

任何想法都会受到赞赏。 感谢。

2 个答案:

答案 0 :(得分:2)

由于您使用的是ModelViewSets,因此您可以覆盖默认操作,如.list(),. retrieve(),. create()等,以执行您想要的操作或创建自定义操作。可以找到ModelViewSets的相关信息herehere

实际上,有很多方法可以解决这个问题,甚至不需要使用ModelViewSet。您实际上可以使用此通用视图。真正的诀窍是通常利用CBV和OOP的力量。下面是一个示例代码,其中提供了单个实例的自定义检索过程,同时保留了ModelViewSet提供的所有其他开箱即用的行为。

class SiteViewSet(viewsets.ModelViewSet):
    serializer_class = SiteSerializer
    queryset = Site.objects.all()

    def retrieve(self, request, *args, **kwargs):
        instance = self.get_object()
        # You can use the serializer_class specified above (SiteSerializer)
        serializer = self.get_serializer(instance)

        # Or perform some other manipulation on your instance first,
        # then use a totally different serializer for your needs
        instance = data_manipulation(instance)
        serializer = AnotherSiteSerializer(instance)

        # Finally return serialized data
        return Response(serializer.data)

        # Or if you want, return random gibberish.
        return Response({'hello': 'world'})    

答案 1 :(得分:1)

我认为您可以覆盖序列化程序的to_representation()方法来解决您的问题:

class SiteSerializer(serializers.ModelSerializer):
    class Meta:
       model = Site
       depth = 1
       exclude = ('title')

    def to_representation(self, instance):
        rep = super(SiteSerializer, self).to_representation(instance)
        if not rep.get('title_modified', ''):
            rep['title_modified'] = instance.title
        return rep

如果title_modified为空,这将返回title_modified标题。用户将始终根据需要处理title_modified。 有关详细信息,请参阅modelserializerAdvanced serializer usage