在 Django REST Framework 中处理嵌套对象表示
Posted
技术标签:
【中文标题】在 Django REST Framework 中处理嵌套对象表示【英文标题】:Handling nested object representations in 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
【问题讨论】:
【参考方案1】:DRF 无法找出measurement
序列化器字段的来源。执行以下操作之一:
-
添加
related_name
:
class Measurement(models.Model):
data = models.ForeignKey(Data, on_delete=models.CASCADE, related_name='measurements')
-
为序列化器字段指定
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 时,一切正常。所以问题是如何使用我上面使用的请求发送这些数据。以上是关于在 Django REST Framework 中处理嵌套对象表示的主要内容,如果未能解决你的问题,请参考以下文章