【问题标题】:Handling nested object representations in Django REST Framework在 Django REST Framework 中处理嵌套对象表示
【发布时间】:2020-07-11 10:44:58
【问题描述】:

我在处理嵌套序列化程序 (DRF) 时遇到了一些问题。

我想用这样的结构收集数据:

{
    'some_tekst': 'test_text',
    'measurements': [
        {'int_test': 1, 'char_test': '1'},
        {'int_test': 2, 'char_test': '2'}
    ]
}

我正在使用文档 (https://www.django-rest-framework.org/api-guide/serializers/#dealing-with-nested-objects) 并且正在查看 (https://medium.com/@raaj.akshar/creating-reverse-related-objects-with-django-rest-framework-b1952ddff1c) 并且仍然有 HTTP 400 响应:

'{"measurements":["此字段为必填项。"]}'

models.py

class Data(models.Model):
    datetime = models.CharField(max_length=100)

    def __str__(self):
        return 'just testing'


class Measurement(models.Model):
    # EDIT:
    # data = models.ForeignKey(Data, on_delete=models.CASCADE) #deleted

    char_test = models.CharField(max_length=100)
    test = models.IntegerField(default=0)


    def __str__(self):
        return self.char_test

serializers.py:

class MeasurementSerializer(serializers.ModelSerializer):
    class Meta:
        model = Measurement
        fields = '__all__'

class DataSerializer(serializers.ModelSerializer):
    # EDIT:
    #measurements = MeasurementSerializer(many=True)
    measurements = MeasurementSerializer(many=True, source='measurement_set')

    class Meta:
        model = Data
        fields = ['datetime', 'measurements']

    # EDIT:
    #def create(self, validated_data):
    #    measurement_validated_data = validated_data.pop('measurements')
    #    data = Data.objects.create(**validated_data)
    #    Measurement.objects.create(data=data, **measurement_validated_data)
    #    return data
    def create(self, validated_data):
        measurement_validated_data = validated_data.pop('measurements')
        data = Data.objects.create(**validated_data)
        for measurement_data in measurement_validated_data:
            Measurement.objects.create(data=data, **measurement_data)
        return data

views.py

class DataViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows groups to be viewed or edited.
    """
    serializer_class = DataSerializer
    queryset = Data.objects.all()


class MeasurementViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows groups to be viewed or edited.
    """
    serializer_class = MeasurementSerializer
    queryset = Measurement.objects.all()

还有我的简单发帖请求:

data = {
    "datetime": "testdatatime",
    "measurements": [
        {'test': 1, 'char_test': '1'},
        {'test': 2, 'char_test': '2'},
    ],
}
r = requests.post(
    'http://127.0.0.1:8000/api/data/',
    data=data,
)

我是不是忘记了什么?

编辑: 有来自 DRF 的 API 端点:

HTTP 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "name": "Data List",
    "description": "API endpoint that allows groups to be viewed or edited.",
    "renders": [
        "application/json",
        "text/html"
    ],
    "parses": [
        "application/json",
        "application/x-www-form-urlencoded",
        "multipart/form-data"
    ],
    "actions": {
        "POST": {
            "datetime": {
                "type": "string",
                "required": true,
                "read_only": false,
                "label": "Datetime",
                "max_length": 200
            },
            "measurements": {
                "type": "field",
                "required": true,
                "read_only": false,
                "label": "Measurements",
                "child": {
                    "type": "nested object",
                    "required": true,
                    "read_only": false,
                    "children": {
                        "id": {
                            "type": "integer",
                            "required": false,
                            "read_only": true,
                            "label": "ID"
                        },
                        "char_test": {
                            "type": "string",
                            "required": true,
                            "read_only": false,
                            "label": "Char test",
                            "max_length": 100
                        },
                        "test": {
                            "type": "integer",
                            "required": false,
                            "read_only": false,
                            "label": "Test",
                            "min_value": -2147483648,
                            "max_value": 2147483647
                        }
                    }
                }
            }
        }
    }
}

编辑 2: django 端(控制台)出错

django_web  | Bad Request: /api/data/
django_web  | [31/Mar/2020 22:54:39] "POST /api/data/ HTTP/1.1" 400 44

【问题讨论】:

    标签: python django serialization django-rest-framework


    【解决方案1】:

    DRF 无法找出measurement 序列化器字段的来源。执行以下操作之一:

    1. 添加related_name:
    class Measurement(models.Model):
        data = models.ForeignKey(Data, on_delete=models.CASCADE, related_name='measurements')
    
    1. 为序列化器字段指定source 属性
    class DataSerializer(serializers.ModelSerializer):
        measurements = MeasurementSerializer(many=True, source='measurement_set')
    

    做一个或另一个,而不是两个。

    另外,您的创建函数中存在逻辑错误

        def create(self, validated_data):
            measurement_validated_data = validated_data.pop('measurements') # Remember, this is an array
            data = Data.objects.create(**validated_data)
            for measurement_data in measurement_validated_data:
                Measurement.objects.create(data=data, **measurement_data)
            return data
    
    

    【讨论】:

    • 您好,感谢您的回复!我编辑了我的帖子 - 你能看一下吗?它仍然不适合我。还是一样的回复 (400) 非常感谢!
    • 您好,您可以粘贴或发送带有您看到的实际回溯/错误的屏幕截图吗? @tomm
    • 您的意思是整个响应吗? (比如 r ? r = requests.post( '127.0.0.1:8000/api/data', data=data, ) 我只有 'Bad Request' - 所以它是 400 代码,正如我之前所说的 "'{"measurements":["This field是必需的。"]}' "。@GrandPhuba
    • 我在上面添加了 django 响应(控制台)(编辑 2)。但没有任何帮助
    • 如我所见,当我使用 ORM 和 QuerySet 时,一切正常。所以问题是如何使用我上面使用的请求发送这些数据。
    猜你喜欢
    • 2017-04-09
    • 1970-01-01
    • 1970-01-01
    • 2013-02-26
    • 2016-01-22
    • 1970-01-01
    • 2022-06-25
    • 2017-04-08
    • 2021-11-30
    相关资源
    最近更新 更多