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


73

我想将一些参数从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')

观看次数

class OneZeroViewSet(viewsets.ModelViewSet):

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

   queryset = OneZero.objects.all()

基本上,我想将基于查询字符串的一些值从视图传递给Serializer类,然后将这些分配给字段。

这些字段实际上不包含在“模型”中,而是动态创建的字段。

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

在这种情况下,任何人都可以帮助我或为我提供更好的选择。


@PauloScardine您能给我简单的例子还是我可以得到帮助的任何链接?我是django的新手,所以为什么听不懂您的话。
Shoaib Ijaz 2014年

1
您所指问题的答案是正确的,请阅读该get_serializer方法的文档并覆盖它以返回序列化程序的自定义实例。
Paulo Scardine 2014年


我还提到了这个问题作为参考,但没有任何细节可以帮助我
Shoaib Ijaz 2014年

1
我已经阅读了文档,但是找不到任何传递额外参数的示例。只是示例如何使用不同的序列化类。那就是为什么我在这里发布问题
Shoaib Ijaz

Answers:


102

对于“ ModelSerializer”构造函数,使用“上下文” arg非常容易。

例如:

鉴于:

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

在序列化器中:

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
...

因此您可以使用“ self.context”获取额外的参数。

参考


12
这不起作用..当我在序列化器中传递带有额外字段的上下文时,该额外字段丢失并且上下文看起来像:{'request': <rest_framework.request.Request object at 0x103a2ba20>, 'view': <api.views.CourseAssignmentViewSet object at 0x10326b828>, 'format': None}
L3K0V 2015年

@redcyb您能帮我这个忙吗stackoverflow.com/questions/62039305/…–
banky

27

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

def get_serializer_context(self):
    return {'user': self.request.user.email}

6
只是覆盖get_serializer_context不会削减它,导致真正的地方,validated_data用context更新的地方是serializer.save()method,由ViewSet.update() -> ViewSet.perform_update()和调用ViewSet.create() -> ViewSet.perform_create()。但要注意的是,它们没有**kwargs随上下文传递给save()。因此,为了混入上下文,我们必须重写perform_createperform_update以便它们将上下文传递给save()
鲍里斯·伯科夫

@andilabs您能帮我这个忙吗?stackoverflow.com/questions/62039305/…–
banky

26

您可以在YourView覆盖get_serializer_context方法中像这样:

class YourView(GenericAPIView):

    def get_serializer_context(self):
        context = super().get_serializer_context()
        context["customer_id"] = self.kwargs['customer_id']
        context["query_params"] = self.request.query_params
        return context

或类似的:

class YourView(GenericAPIView):
    def post(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)

        serializer.context["customer_id"] = request.user.id
        serializer.context["query_params"] = request.query_params

        serializer.is_valid(raise_exception=True)
        ...

随时随地在你的序列化,你可以得到它。例如,在自定义方法中:

class YourSerializer(ModelSerializer):
    def get_alternate_name(self, obj):
        customer_id = self.context["customer_id"]
        query_params = self.context["query_params"]
        ...

您能帮我这个
忙吗


拯救了我的一天!我长期以来一直在寻找这个商品
Shamsul Arefin Sajib

9

我写的一个旧代码可能对过滤嵌套的序列化程序很有帮助:

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')

如何覆盖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):
       .....

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


4
正是我获取查询参数所需要的,谢谢!请注意,显示的代码已被弃用。要获取参数值,现在看起来像self.context['request'].query_params.get()
尼克·布雷迪
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.