Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rest Framework Serializer Method

I have the following Serializer using the Django REST Framework.

This is what I have so far...

serializer.py

class ProductSerializer(serializers.ModelSerializer):

    score = serializers.SerializerMethodField('get_this_score')

    class Meta:
        model = Product
        fields = ('id', 'title', 'active', 'score')

    def get_this_score(self, obj):

        profile = Profile.objects.get(pk=19)
        score = [val for val in obj.attribute_answers.all() if val in profile.attribute_answers.all()]
        return (len(score))

urls.py

 url(r'^products/(?P<profile_id>.+)/$', ProductListScore.as_view(), name='product-list-score'),

There are a few issues with this snippet of code.

1) The pram pk=19 is hardcoded it should be self.kwargs['profile_id']. I have tried and tried, but I don't know how to pass kwarg into the method and cannot get profile_id to work. i.e. I cannot get it from the url.

2) Should any of this code be in models? I have tried adding to models, but again can pass the args.

models.py i.e. method class

     def get_score(self, profile):

        score = [val for val in self.attribute_answers.all() if val in 
profile.attribute_answers.all()]
            return len(score)
like image 897
jason Avatar asked Feb 17 '13 13:02

jason


2 Answers

Serializers are passed a context dictionary, which contains the view instance, so you could get the profile_id by doing something like this:

view = self.context['view']
profile_id = int(view.kwargs['profile_id'])

However in this case I don't think you need to do that as 'obj' will in any case be set to the profile instance.

And yes, you could put the 'get_this_score' method on the model class instead. You'd still need the 'SerializerMethodField', but it would simply call 'return obj.get_this_score(...)', setting any arguments from the serializer context.

Note that the serializer context will also include 'request', so you can also access 'request.user' if needed.

like image 114
Tom Christie Avatar answered Sep 23 '22 05:09

Tom Christie


To answer jason's question response to Tom's answer you can access the request object via the same context mechanism like so. You reference the request objects from the ModelMethod definition, you don't pass them. I was able to use this to access the current request.user object as below:

class ProductSerializer(serializers.ModelSerializer):
    score = serializers.SerializerMethodField('get_this_score')

    class Meta:
        model = Product
        fields = ('id', 'title', 'active', 'score')

    def get_this_score(self, obj):

        profile = self.context['request'].user
        score = [val for val in obj.attribute_answers.all() if val in profile.attribute_answers.all()]
        return (len(score))
like image 30
Emeka Avatar answered Sep 22 '22 05:09

Emeka