我怎样序列化一个对象列表并在验证通过时返回该对象?

huangapple go评论67阅读模式
英文:

How can I serialize a list of objects and return the object if validated?

问题

我在我的视图集类中有以下内容:

    serializer = ResponsesSerializer(data=queryset, many=True)
    serializer.is_valid(raise_exception=True)
    validated_data = serializer.validated_data

    response = Response(validated_data, status=status.HTTP_200_OK)
    return response

用于测试的,`queryset` 是下面传递给我的 `ResponsesSerializer` 的对象列表,其中只有第一个对象有一个 `record` 键:

    queryset = [
                    {
                        "C_Ethnicity.r1": 0,
                        "C_Ethnicity.r2": 0,
                        "EaseOfFind.r1": 0,
                        "EaseOfFind.r2": 1,
                        "Leg.r1": 0,
                        "Leg.r2": 0,
                        "record": 17
                    },
                    {
                        "C_Ethnicity.r1": 0,
                        "C_Ethnicity.r2": 0,
                        "EaseOfFind.r1": 0,
                        "EaseOfFind.r2": 1,
                        "Leg.r1": 1,
                        "Leg.r2": 0,
                    },
                        {
                        "C_Ethnicity.r1": 0,
                        "C_Ethnicity.r2": 0,
                        "EaseOfFind.r1": 0,
                        "EaseOfFind.r2": 1,
                        "Leg.r1": 1,
                        "Leg.r2": 0,
                    }
                ]

在响应中,序列化器对没有 `record` 键的最后两个对象提出了预期的验证错误,但我不知道为什么第一个对象是空的:

    [
        {},
        {
            "non_field_errors": [
                "字典中缺少 'record' 键。"
            ]
        },
        {
            "non_field_errors": [
                "字典中缺少 'record' 键。"
            ]
        }
    ]

这是 `ResponsesSerializer`:

    class ResponsesSerializer(serializers.Serializer):
        def to_internal_value(self, data):
            return data
    
        def validate(self, data):
            if 'record' not in data:
                raise serializers.ValidationError("字典中缺少 'record' 键。")
            return data

我对序列化器不熟悉,在这种情况下,我只想添加验证条件,以便可以测试列表中的每个对象,即是否有一个 `record` 键或特定长度的项,并忽略任何其他键。
英文:

I have the below in one of my viewset classes:

    serializer = ResponsesSerializer(data=queryset, many=True)
    serializer.is_valid(raise_exception=True)
    validated_data = serializer.validated_data

    response = Response(validated_data, status=status.HTTP_200_OK)
    return response

For testing purposes, queryset is the below list of objects that is being passed to my ResponsesSerializer, where only the first object has a record key:

queryset = [
                {
                    "C_Ethnicity.r1": 0,
                    "C_Ethnicity.r2": 0,
                    "EaseOfFind.r1": 0,
                    "EaseOfFind.r2": 1,
                    "Leg.r1": 0,
                    "Leg.r2": 0,
                    "record": 17
                },
                {
                    "C_Ethnicity.r1": 0,
                    "C_Ethnicity.r2": 0,
                    "EaseOfFind.r1": 0,
                    "EaseOfFind.r2": 1,
                    "Leg.r1": 1,
                    "Leg.r2": 0,
                },
                    {
                    "C_Ethnicity.r1": 0,
                    "C_Ethnicity.r2": 0,
                    "EaseOfFind.r1": 0,
                    "EaseOfFind.r2": 1,
                    "Leg.r1": 1,
                    "Leg.r2": 0,
                }
            ]

In the response, the serializer expectedly raises a validation error for the last two objects without a record key, but I don't know why the first object is then empty:

[
    {},
    {
        "non_field_errors": [
            "Missing 'record' key in dictionary."
        ]
    },
    {
        "non_field_errors": [
            "Missing 'record' key in dictionary."
        ]
    }
]

This is the ResponsesSerializer:

class ResponsesSerializer(serializers.Serializer):
    def to_internal_value(self, data):
        return data

    def validate(self, data):
        if 'record' not in data:
            raise serializers.ValidationError("Missing 'record' key in dictionary.")
        return data

I'm new to serializers, and in this case I just want to add validation criteria that each object in the list can be tested for, i.e having a record key or a certain length of items, and ignoring any other keys.

答案1

得分: 0

但我不知道为什么第一个对象是空的。

序列化器验证列表中的所有元素,只有当所有项都有效时才有效。

如果一个或多个项无效,它会返回错误。它通过一个字典列表来实现,对于给定数据中的每个项目,错误列表中都有一个项目。这是有道理的,因为人们可能想知道哪个项目适用于哪些错误。因此,第一个字典包含了第一个项目的错误。

由于第一个项目因此不包含错误,它是一个空字典,意味着第一个项目是有效的,但其他项目都无效。

通常只有在所有项目匹配时才插入数据才有意义,因为人们通常希望操作是原子性的:要么全部成功(一起),要么全部都不成功。

我只是想添加验证标准,即列表中的每个对象都可以进行测试,例如具有记录键或特定长度的项目。

通常您不会自己实现validate。您会向序列化器添加字段,如:

class ResponsesSerializer(serializers.Serializer):
    record = serializer.CharField(<b>required=True</b>)

这将检查是否确实有一个名为record的字符串字段。

或特定长度的项目。

在这种情况下,您可以使用ListSerializer,这实质上就是many=True的作用。您可以轻松地构建它:

serializer = ResponsesSerializer(many=True<b>, min_length=5, max_length=5</b>)

这将要求请求中恰好有五个项目。

英文:

> but I don't know why the first object is then empty.

The serializer validates all elements in the list, and only is valid in case all items are valid.

If one or more items are invalid, it returns the errors. It does that with a list of dictionaries where for each item in the given data, it has an item in the error list. This makes sense since one probably wants to know for which item which errors apply. So the first dictionary contains errors for the first item.

Since the first item thus contains no errors, it is an empty dictionary, meaning that the first item is valid, but the rest is not.

It probably makes a lot of sense to only insert data if all items match, since one usually wants operations to be atomically: either all succeed (together) or none at all.

> I just want to add validation criteria that each object in the list can be tested for, i.e having a record key or a certain length of items.

Typically you don't implement validate yourself. You add fields to the serializer, like:

<pre><code>class ResponsesSerializer(serializers.Serializer):
record = serializer.CharField(<b>required=True</b>)</code></pre>

this will then check if there is indeed a record field that is a string.

> or a certain length of items.

In that case you can work with a ListSerializer, which is essentially what a many=True does. You can easily construct this with:

<pre><code>serializer = ResponsesSerializer(many=True<b>, min_length=5, max_length=5</b>)</code></pre>

this will require that there are exactly five items in the request.

huangapple
  • 本文由 发表于 2023年7月3日 05:28:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/76600870.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定