在初始化django序列化器时出现问题,在选择字段中使用了额外的变量



我有一个这样的django序列化器

# urls
urlpatterns = [
path("cat", CatView.as_view(), name="cat")
]

# serializers
class CatSerializer(serializers.Serializer):
name = serializers.ChoiceField(choices=[])
def __init__(self, *args, **kwargs):
self.names = kwargs.pop("names")
self.fields["name"].choices = self.names
super().__init__(self, *args, **kwargs)
# views
class CatView(APIView):
def __init__(self, *arg, **kwargs):
super().__init__(*arg, **kwargs)
self.names = ['a', 'b', 'c']
def get_serializer(self, *args, **kwargs):
serializer_class = CatSerializer
return serializer_class(
*args, **kwargs,
names=self.names
)
def post(self, request):
request_body = request.body
serializer = self.get_serializer(
data=json.loads(request_body),
)
is_data_valid = serializer.is_valid()
if is_data_valid:
serialized_data = serializer.data
return Response({"message": "success", "serialized-data": serialized_data})
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

这是我问题的简化版。

我正在尝试动态初始化一个序列化器,它有一个选择字段name,它的选择来自于初始化后传递给序列化器的kwargs。

如果我在这个类上调用OPTIONS方法它返回

{
"name": "Cat",
"description": "",
"renders": [
"application/json",
"text/html"
],
"parses": [
"application/json",
"application/x-www-form-urlencoded",
"multipart/form-data"
],
"actions": {
"POST": {
"name": {
"type": "choice",
"required": true,
"read_only": false,
"label": "Name",
"choices": [
{
"value": "a",
"display_name": "a"
},
{
"value": "b",
"display_name": "b"
},
{
"value": "c",
"display_name": "c"
}
]
}
}
}
}

,如果我发出POST请求并传递有效载荷

{
"name": "d"
}

它正确返回

{"name":[""d" is not a valid choice."]}

但是如果我传递一个有效载荷

{
"name": "a"
}

我看到这个错误

AttributeError: Got AttributeError when attempting to get a value for field `name` on serializer `CatSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `CatSerializer` instance.
Original exception text was: 'CatSerializer' object has no attribute 'name'.

有什么想法吗?

尝试创建一个dynamic_serializer_method,如下所示:

def dynamic_serializer(choices):
class CatSerializer(serializers.Serializer):
name = serializers.ChoiceField(choices=choices)
return CatSerializer

和在你的Viewset上:

def get_serializer(self, *args, **kwargs):
serializer_class = dynamic_serializer(self.names)
return serializer_class(*args, **kwargs)

最新更新