将额外的参数传递给Django Rest Framework中的Serializer Class

Sho*_*jaz 56 python django rest django-rest-framework

我想从Viewset向DRF Serializer类传递一些参数,所以我试过这个:

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')
Run Code Online (Sandbox Code Playgroud)

查看

class OneZeroViewSet(viewsets.ModelViewSet):

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

   queryset = OneZero.objects.all()
Run Code Online (Sandbox Code Playgroud)

基本上我想基于querystring从视图传递一些值到Serializer类,然后将这些值分配给字段.

这些字段不包含在Model中,实际上是动态创建的字段.

在这个问题stackoverflow中的情况相同,但我无法理解答案.

任何人都可以在这种情况下帮助我或建议我更好的选择.

小智 76

使用"ModelSerializer"构造函数的"context"arg非常容易.

例如:

在视图中:

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

在序列化器中:

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
...
Run Code Online (Sandbox Code Playgroud)

所以你可以使用"self.context"来获得额外的参数.

参考

  • 这不起作用..当我在序列化程序中传递带有额外字段的上下文时,这个额外字段丢失,上下文看起来像:`{'request':<rest_framework.request.Request object at 0x103a2ba20>,'view':<api. views.CourseAssignmentViewSet对象位于0x10326b828>,'format':无}` (9认同)

and*_*abs 21

为了实现redcyb的答案 - 考虑在您的视图中使用get_serializer_context方法GenericAPIView,如下所示:

def get_serializer_context(self):
    return {'user': self.request.user.email}
Run Code Online (Sandbox Code Playgroud)

  • 只是重写`get_serializer_context`不会削减它,导致真实的地方,`validated_data`更新上下文是`serializer.save()`方法,由`ViewSet.update() - > ViewSet.perform_update调用( )`和`ViewSet.create() - > ViewSet.perform_create()`.但问题是他们没有将带有上下文的`**kwargs`传递给`save()`.因此,为了混合上下文,我们必须覆盖`perform_create`和`perform_update`,以便它们将上下文传递给`save()`. (4认同)

M.V*_*oid 16

你需要在View覆盖get_serializer_context方法中这样:

def get_serializer_context(self):
    return {"customer_id": self.kwargs['customer_id']}
Run Code Online (Sandbox Code Playgroud)

serializer你可以在任何地方得到它:

customer_id = self.context["customer_id"]
Run Code Online (Sandbox Code Playgroud)


yea*_*ske 8

我编写的旧代码,可能有助于过滤嵌套的序列化程序:

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')
Run Code Online (Sandbox Code Playgroud)

如何覆盖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):
       .....
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助人们寻找这个.

  • 正是我需要获取查询参数,谢谢!请注意,已弃用显示的代码.为了获得param值,它现在看起来像`self.context ['request'].query_params.get()`. (4认同)