在DRF

时间:2015-11-25 07:33:46

标签: python django django-rest-framework

我正在使用django-rest-framework-mongoengine作为个人项目。我希望能够在列表请求中发送额外的数据。为此目的,我写了2个mixin:

UserSearializerContextMixin:收集列表中存在的所有实例的用户ID列表。

class UserSerializerContextMixin(object):
    user_lookup_field = 'user_id'
    user_fields_required = ['id','full_name','image','level']
    _user_ids = []

    def update_context(self,user_id):
        if not self.context.get('user_ids'):
            self.context['user_ids'] = [user_id]
        else:
            self.context['user_ids'].append(user_id)

    def to_representation(self,instance):
        self.update_context(getattr(instance,self.user_lookup_field))
        return super(UserSerializerContextMixin,self).to_representation(instance)

UserSerializerDataMixin:使用to_representation部分中准备的上下文覆盖data属性。

class UserSerializerDataMixin(object):

    @property   
    def data(self):

        ret = super(UserSerializerDataMixin, self).data
        // Override the data
        return ReturnDict(ret, serializer=self)

然后对于我的序列化程序,我会做这样的事情:

class DFSerializer(UserSerializerContextMixin,UserSerializerDataMixin,DocumentSerializer):
    //Fields and all

但不知何故,代码只是没有输入重写的数据属性。我猜逻辑上应该通过扩展mixin来覆盖data属性。但这不会发生在这里。

可能是什么原因以及如何解决?

1 个答案:

答案 0 :(得分:0)

这是一个非常古老的问题,但以防万一有人偶然发现此问题:

我来到这里是因为我不满意drf如何要求TemplateHTMLRenderer与其他渲染器使用不同的序列化器输出。因此,可能的解决方案之一涉及覆盖data属性以返回包含序列化器和数据的字典,而不是包含相同序列化器和数据的ReturnList返回。

无论如何,这里的问题是,对于ViewSet中的 listing 记录,不是直接实例化序列化程序,而是ListSerializer实例,然后ListSerializer为每个特定实例调用序列化程序记录要序列化。

一个丑陋的补丁“修复”了这个问题,就像这样:

class YourViewSet(SomeBaseViewSet):

....

def get_serializer(self, *args, **kwargs):

    res = super().get_serializer(*args, **kwargs)

    class Patch(res.__class__):

        @property
        def data(self):
            request = self.context['request']
            if isinstance(request.accepted_renderer, TemplateHTMLRenderer):
                return dict(data=super().data,
                            serializer=self.child if isinstance(self, serializers.ListSerializer) else self)
            return super().data

    res.__class__ = Patch

    return res

截至撰写本文时,我仍在确定解决我的特定问题(TemplateHTMLRenderer需要不同的序列化输出)的最佳方法是什么。接下来,我正在测试覆盖渲染器,但是以上内容确实为我“解决了”我的问题,并且还解释了为什么代码不符合OP的预期。