Pass extra arguments to Serializer Class in Django

2019-01-21 15:55发布

I want to pass some arguments to DRF Serializer class from Viewset, so for I have tried this:

class OneZeroSerializer(rest_serializer.ModelSerializer):

    def __init__(self, *args, **kwargs):
        print args # show values that passed

    location = rest_serializer.SerializerMethodField('get_alternate_name')

    def get_alternate_name(self, obj):
        return ''


    class Meta:
        model = OneZero

        fields = ('id', 'location')

Views

class OneZeroViewSet(viewsets.ModelViewSet):

   serializer_class = OneZeroSerializer(realpart=1)
   #serializer_class = OneZeroSerializer

   queryset = OneZero.objects.all()

Basically I want to pass some value based on querystring from views to Serializer class and then these will be allocate to fields.

These fields are not include in Model in fact dynamically created fields.

Same case in this question stackoverflow, but I cannot understand the answer.

Can anyone help me in this case or suggest me better options.

4条回答
放我归山
2楼-- · 2019-01-21 16:32

It's very easy with "context" arg for "ModelSerializer" constructor.

For example:

in view:

my_objects = MyModelSerializer(
    input_collection, 
    many=True, 
    context={'user_id': request.user.id}
).data

in serializers:

class MyModelSerializer(serializers.ModelSerializer):
...

    is_my_object = serializers.SerializerMethodField('_is_my_find')
...

    def _is_my_find(self, obj):
        user_id = self.context.get("user_id")
        if user_id:
            return user_id in obj.my_objects.values_list("user_id", flat=True)
        return False
...

so you can use "self.context" for getting extra params.

Reference

查看更多
仙女界的扛把子
3楼-- · 2019-01-21 16:37

To fulfill the answer of redcyb - consider using in your view the get_serializer_context method from GenericAPIView, like this:

def get_serializer_context(self):
    return {'user': self.request.user.email}
查看更多
孤傲高冷的网名
4楼-- · 2019-01-21 16:46

A old code I wrote, that might be helpful- done to filter nested serializer:

class MySerializer(serializers.ModelSerializer):

    field3  = serializers.SerializerMethodField('get_filtered_data')

    def get_filtered_data(self, obj):
        param_value = self.context['request'].QUERY_PARAMS.get('Param_name', None)
        if param_value is not None:
            try:
                data = Other_model.objects.get(pk_field=obj, filter_field=param_value)
            except:
                return None
            serializer = OtherSerializer(data)
            return serializer.data
        else:
            print "Error stuff"

    class Meta:
        model = Model_name
        fields = ('filed1', 'field2', 'field3')

How to override get_serializer_class:

class ViewName(generics.ListAPIView):

    def get_serializer_class(self):
        param_value = self.context['request'].QUERY_PARAMS.get('Param_name', None)
        if param_value is not None:
            return Serializer1
        else:
            return Serializer2

    def get_queryset(self):
       .....

Hope this helps people looking for this.

查看更多
Juvenile、少年°
5楼-- · 2019-01-21 16:49

You need in the View override get_serializer_context method like this:

def get_serializer_context(self):
    return {"customer_id": self.kwargs['customer_id']}

and anywhere in the serializer you can get it:

customer_id = self.context["customer_id"]
查看更多
登录 后发表回答