【问题标题】:Validated data fields differs from data fields Django Rest Nested serializers验证的数据字段不同于数据字段 Django Rest 嵌套序列化程序
【发布时间】:2020-09-29 12:14:54
【问题描述】:

所以我在 django 中使用序列化程序并想更改我的响应中的字段名称,当我意识到我的更改没有被计入计数时,我做了一些挖掘,发现我的验证数据与我的数据不同。

我的目标是为序列化程序提供一个 python 对象,该序列化程序的字段与我想要返回的名称不同,因此我在我的字段中使用了 'source=' 参数。

请注意,更改 python 对象字段的名称不是一种选择。

这是 python 对象:

class Flow(object):
    """Just a regular python object"""
    def __init__(self, name=None, flow_uid=None, data_type=None, parent=None, container=None):
        """This has more fields than the serializer is waiting"""
        self._parent = None
        self._container = None
        self.name = name
        self.data_type = data_type
        self.flow_uid = flow_uid

以及以下序列化程序(我使用的是嵌套表示)
serializers.py

from rest_framework.fields import CharField, IntegerField, ListField, JSONField
from rest_framework.serializers import Serializer

class OutputSerializer(Serializer):
    uid = CharField(max_length=36)
    name = CharField(max_length=100)
    description = CharField(max_length=100)


class FlowSerializer(Serializer):
    uid = CharField(source='flow_uid', max_length=36) # I want 'uid' in my response not 'flow_uid'
    name = CharField(max_length=100)
    data_type = CharField(max_length=100)
    class Meta:
        fields = '___all___'

    def to_representation(self, instance):
        instance = super(FlowSerializer, self).to_representation(instance)
        #Here instance = OrderedDict([('uid', 'uid_value'), ('name', 'name_value'), ('data_type', 'data_value')])
        return instance


class FlowOutputSerializer(OutputSerializer):
    columns = FlowSerializer(many=True)

viewsets.py

class AddTransformationViewSet(ViewSet):
    """Handle available "actions" for BrickModel operations"""

    def list(self, request, parent_lookup_analyses: str):
        """The method I call for this test"""

        flow1 = Flow(name="name1", flow_uid='flow_uid_value1', data_type='str')
        flow2 = Flow(name="name2", flow_uid='flow_uid_value2', data_type='str')
        flow1_ser = FlowSerializer(flow1)
        flow2_ser = FlowSerializer(flow2)

        dummy_col = {
            "name": "output_name",
            "description": "output_description",
            "uid": "output_uid",
            "columns":
            [
                flow2_ser.data, # Debug: {'uid': 'flow_uid_value2', 'name': 'name2', 'data_type': 'str'}
                flow1_ser.data # Debug: {'uid': 'flow_uid_value1', 'name': 'name1', 'data_type': 'str'}
            ]
        }
        #Debug dummy_col: {'name': 'output_name', 'description': 'output_description', 'uid': 'output_uid', 'columns': [{'uid': 'flow_uid_value2', 'name': 'name2', 'data_type': 'str'}, {'uid': 'flow_uid_value1', 'name': 'name1', 'data_type': 'str'}]} 


        dummy_serializer: FlowOutputSerializer = FlowOutputSerializer(data=dummy_col)
        dummy_serializer.is_valid(raise_exception=True)
        # Debug dummy_serializer.data: {'uid': 'output_uid', 'name': 'output_name', 'description': 'output_description', 'columns': [OrderedDict([('uid', 'flow_uid_value2'), ('name', 'name2'), ('data_type', 'str')]), OrderedDict([('uid', 'flow_uid_value1'), ('name', 'name1'), ('data_type', 'str')])]}
        # Debug dummy_serializer.validated_data: OrderedDict([('uid', 'output_uid'), ('name', 'output_name'), ('description', 'output_description'), ('columns', [OrderedDict([('flow_uid', 'flow_uid_value2'), ('name', 'name2'), ('data_type', 'str')]), OrderedDict([('flow_uid', 'flow_uid_value1'), ('name', 'name1'), ('data_type', 'str')])])])
        return Response(data=dummy_serializer.validated_data, status=status.HTTP_201_CREATED)

预期响应:

{
    ...
    "columns": [
        {
            "uid": "flow_uid_value2",
            "name": "name2",
            "data_type": "str"
        },
        {
            "uid": "flow_uid_value1",
            "name": "name1",
            "data_type": "str"
        }
    ]
}

我得到什么(我希望 'flow_uid' 是 'uid'):

{
    ...
    "columns": [
        {
            "flow_uid": "flow_uid_value2",
            "name": "name2",
            "data_type": "str"
        },
        {
            "flow_uid": "flow_uid_value1",
            "name": "name1",
            "data_type": "str"
        }
    ]
}

在这种情况下使用 .data 而不是 .validated_data 有什么特别的危险吗? 这种行为的原因是什么?

【问题讨论】:

    标签: python json django django-rest-framework django-serializer


    【解决方案1】:

    在这种情况下使用 .data 而不是 .validated_data 有什么特别的危险吗?这种行为的原因是什么?

    serializer.validated_data 旨在与 Python 对象一起使用。因此,由于自定义的source 值,它将暴露flow_uid。

    serializer.data 将是save() 在save 被调用后的序列化结果。

    因此,您应该始终在您的回复中使用serializer.data,并在与模型或内部项目代码交互的任何代码中保留serializer.validated_data:

    Response(data=dummy_serializer.data, status=status.HTTP_201_CREATED)
    

    【讨论】:

    • 在这种情况下,如果我希望在响应中使用“uid”而不是“flow_uid”,同时保持 python 对象的结构完整,那么正确的方法是什么?
    • 感谢您的帮助,但是我觉得这里还是有问题,我仍然希望进行基本的字段验证。例如,我尝试将Integer 提供给我的Charfield,它只是将其转换为str,而不是告诉我有什么问题。可能与:stackoverflow.com/questions/53963371/…
    • DRF char 字段代码说:“我们允许将基本数字强制转换为字符串,但其他类型应该失败。例如,不清楚布尔值是否应该表示为 true 或 True ,而诸如列表之类的组合很可能是用户错误。”
    猜你喜欢
    • 1970-01-01
    • 2017-11-12
    • 1970-01-01
    • 2014-11-20
    • 2018-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-22
    相关资源
    最近更新 更多