SerializerMethodField的get_user_permissions函数未调用,求技术解决方案
问题原因及解决办法
核心原因
SerializerMethodField 是只读字段,仅在序列化阶段(将模型对象转为响应数据)触发对应的get_xxx方法;而你当前的视图动作是处理PATCH/PUT请求,处于反序列化阶段(解析请求输入数据),这个阶段SerializerMethodField会被完全忽略,自然不会调用get_user_permissions,连print(1)都不会执行。
针对性解决方案
根据你的实际需求分两种情况处理:
情况1:仅需接收前端传来的权限数据执行移除操作
直接把user_permissions改成支持反序列化的字段类型,比如PrimaryKeyRelatedField:
class RemovePermissionsSerializer(serializers.ModelSerializer): # 改用支持接收输入的字段,many=True表示接收多个权限ID user_permissions = serializers.PrimaryKeyRelatedField( many=True, queryset=Permission.objects.all() ) class Meta: model = User fields = ["user_permissions"]
这样在视图中调用serializer.validated_data.get("user_permissions")就能正常拿到前端传入的权限数据,无需get_user_permissions方法。
情况2:处理完移除操作后,需要返回用户更新后的权限数据
拆分输入、输出逻辑:用一个序列化器处理请求输入,另一个带SerializerMethodField的序列化器处理响应输出:
# 处理输入的序列化器 class RemovePermissionsInputSerializer(serializers.ModelSerializer): user_permissions = serializers.PrimaryKeyRelatedField( many=True, queryset=Permission.objects.all() ) class Meta: model = User fields = ["user_permissions"] # 处理输出的序列化器(保留你的SerializerMethodField) class RemovePermissionsOutputSerializer(serializers.ModelSerializer): user_permissions = serializers.SerializerMethodField() def get_user_permissions(self, instance): print(1) # 你的自定义逻辑,比如返回权限的名称/编码等 return [perm.codename for perm in instance.user_permissions.all()] class Meta: model = User fields = ["user_permissions"] # 视图动作修改 @action( methods=["patch", "put"], detail=True, url_name="remove-permissions", url_path="remove-permissions" ) def remove_permissions_request(self, request, pk): # 第一步:解析请求输入 input_serializer = RemovePermissionsInputSerializer(data=request.data) input_serializer.is_valid(raise_exception=True) user = self.get_object() user_permissions = input_serializer.validated_data.get("user_permissions") User.remove_permissions(user, user_permissions) # 执行移除逻辑 # 第二步:序列化用户最新权限,返回响应 output_serializer = RemovePermissionsOutputSerializer(user) return Response(output_serializer.data, status=status.HTTP_200_OK)
此时执行到序列化输出阶段,get_user_permissions就会被正常调用,print(1)也会输出。
内容的提问来源于stack exchange,提问作者eksoo
相关产品推荐
相关产品推荐

