I am using django-rest-framework-mongoengine for a personal project. I want to be able to send extra data in list requests. I have written 2 mixins for that purpose:
UserSearializerContextMixin: Collects the list of user ids for all the instances present in the list.
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: Override the data property using the context prepared in to_representation part.
class UserSerializerDataMixin(object):
@property
def data(self):
ret = super(UserSerializerDataMixin, self).data
// Override the data
return ReturnDict(ret, serializer=self)
Then for my serializer I do something like this:
class DFSerializer(UserSerializerContextMixin,UserSerializerDataMixin,DocumentSerializer):
//Fields and all
But somehow the code just does not enter the overridden data property. I guess logically the data property should be overridden by extending the mixin. But it does not happen here.
What could possibly be the reason and how to resolve?
This is a super old question, but just in case somebody else stumbles upon this:
I came here because I was unhappy how drf requires a different serializer output for TemplateHTMLRenderer than it does for the other renderers. So one of the possible solutions involved overriding data
property to return a dict with serializer & data instead of ReturnList
containing the same serializer & data.
Anyway, the problem here is that for listing records in the ViewSet, it is not your serializer instanced directly, but a ListSerializer instead and that ListSerializer then invokes your serializer for each particular record to be serialized.
An ugly patch "fixing" this problem could be made like so:
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
As of time of this writing, I'm still deciding what the best approach for solving my particular problem (TemplateHTMLRenderer requiring different serialized output) is. I'm testing overriding the renderer next, but the above does "solve" my issue for me and it also explains why code didn't behave to OP's expectations.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With