我正在将 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 属性。但这里不会发生。
可能是什么原因以及如何解决?
这是一个非常古老的问题,但以防万一其他人偶然发现这个:
我来到这里是因为我不高兴 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的期望。
所以现在最简单的方法(以及记录的方法)是创建一个自定义
ListSerializer
,然后使用
list_serializer_class
的
Meta
让 DRF 使用自定义序列化器。详细一点:
class CustomListSerializer(serializers.ListSerializer):
def data(self):
pass
list_serializer_class
class MyCustomSerializer(serializers.Serializer):
...
class Meta:
list_serializer_class = CustomListSerializer
文档可在此处获取:https://www.django-rest-framework.org/api-guide/serializers/#customizing-listserializer-behavior