在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')
视图
class OneZeroViewSet(viewsets.ModelViewSet):
serializer_class = OneZeroSerializer(realpart=1)
#serializer_class = OneZeroSerializer
queryset = OneZero.objects.all()
基本上,我想根据查询字符串的值,从视图传递一些信息到序列化器类,然后这些信息会被分配到字段上。
这些字段实际上并不在模型中,而是动态创建的字段。
这个问题和stackoverflow上的一个问题类似,但我看不懂那个答案。
有没有人能帮我解决这个问题,或者给我更好的建议呢?
8 个回答
1
如果你的查询是一个元素列表,下面是元素的列表:
my_data = DataSerializers(queryset_to_investigate,
many=True, context={'value_to_pass': value_passed}
如果是单个数据查询,情况如下:
my_data = DataSerializers(queryset_to_investigate,
context={'value_to_pass': value_passed}
接下来在序列化器中:
class MySerializer(serializers.ModelSerializer):
class Meta:
fields = '__all__'
model = 'Name_of_your_model'
def on_representation(self, value):
serialized_data = super(MySerializer, self).to_representation(value)
value_as_passed = self.context['value_to_pass']
# ..... do all you need ......
return serialized_data
如你所见,在on_representation
里面打印self,你会看到:query_set: <object (x)>, context={'value_to_pass': value_passed}
这是一种更简单的方法,你可以在任何包含self作为参数的序列化器函数中使用这个方法。
14
这是我以前写的一段老代码,可能对你们有帮助——用来过滤嵌套的序列化器:
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):
.....
希望这能帮助到正在寻找这个的人。
29
为了回答redcyb的问题,可以考虑在你的视图中使用GenericAPIView
里的get_serializer_context
方法,像这样:
def get_serializer_context(self):
return {'user': self.request.user.email}
52
你可以在 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"]
...
154
使用“context”参数来创建“ModelSerializer”非常简单。
比如说:
在视图中:
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”来获取额外的参数了。