我的网站上有一个测试对象,试图将其正确地插入数据库。 这是带有嵌套产品数据的订单对象。 这是前端发布JSON的示例:
{
"phone": "123456789",
"first_name": "name",
"delivery_date": "2020-01-06",
"delivery_time": 2,
"address": "address",
"comment": "comment",
"payment": 0,
"order_items": [
{
"quantity": 2,
"pizza": 1
},
{
"quantity": 3,
"pizza": 2
}
]
}
这是我的serializers.py
class OrderItemSerializer(serializers.ModelSerializer):
quantity = serializers.IntegerField()
pizza = serializers.SerializerMethodField()
print(pizza, quantity)
def get_pizza(self, obj):
print(obj.pizza.id)
return obj.pizza.id
class Meta:
model = OrderItem
fields = ('quantity',
'pizza',)
class OrderSerializer(serializers.ModelSerializer):
order_items = serializers.SerializerMethodField()
"""
Calculate order_items field
"""
def get_order_items(self, obj):
items = obj.orderitem_set.all()
print(obj)
print(items)
return OrderItemSerializer(items, many=True).data
class Meta:
model = Order
fields = ('phone',
'first_name',
'delivery_date',
'delivery_time',
'address',
'comment',
'payment',
'order_items',)
结果,order_items
始终为空:
"order_items": []
我正在使用Swagger测试和记录API。我可以直接从那里发布订单,没有错误,但是即使手动添加订单项目,它们也不会出现在服务器响应正文中。这必须表示我没有正确处理嵌套对象。
POST
{
"phone": "123456",
"first_name": "string",
"delivery_date": "2000-10-21",
"delivery_time": 2,
"address": "string",
"comment": "string",
"payment": 0,
"order_items": [
{"pizza": 2,"quantity": 3},
{"pizza": 1,"quantity": 4}]
}
201,响应正文:
{
"phone": "123456",
"first_name": "string",
"delivery_date": "2000-10-21",
"delivery_time": 2,
"address": "string",
"comment": "string",
"payment": 0,
"order_items": []
}
我还在上面的代码中设置了一些print
行,看来OrderItemSerializer
根本没有被使用。
get_order_items
打印订单ID和一个空数组,而get_pizza
在网站上进行订单时不打印任何内容。
答案 0 :(得分:2)
您需要重写序列化程序的create()
方法来制作writable nested serializers。
尝试这样的事情:
class OrderSerializer(serializers.ModelSerializer):
order_items = serializers.SerializerMethodField()
"""
Calculate order_items field
"""
def get_order_items(self, obj):
items = obj.orderitem_set.all()
print(obj)
print(items)
return OrderItemSerializer(items, many=True).data
class Meta:
model = Order
fields = ('phone',
'first_name',
'delivery_date',
'delivery_time',
'address',
'comment',
'payment',
'order_items',)
def create(self, validated_data):
items_data = validated_data.pop('order_items')
order = Order.objects.create(**validated_data)
for item_data in items_data:
OrderItem.objects.create(order=order, **item_data)
return order
此外,您可以仅将OrderItemSerializer
用作字段,而不使用SerializerMethodField
。您可以使用source
参数指定字段source:
order_items = serializers.OrderItemSerializer(many=True, source="orderitem_set")
答案 1 :(得分:0)
最终我想到了这个。
我必须向order_items
对象添加一个Order
变量,该变量没有以任何方式使用,只是浪费了DB中的空间。即使这不是很大的浪费,但在任何情况下我都不认为这是编写代码的好方法。
如果有人可以在评论或其他答案中提出更好的建议,我也会尝试一下。
from rest_framework import serializers
from .models import Order, OrderItem
import copy
class OrderItemSerializer(serializers.ModelSerializer):
class Meta:
model = OrderItem
fields = ('quantity',
'pizza',)
class OrderSerializer(serializers.ModelSerializer):
order_items = OrderItemSerializer(many=True)
class Meta:
model = Order
fields = ('phone',
'first_name',
'delivery_date',
'delivery_time',
'address',
'comment',
'payment',
'order_items')
def create(self, validated_data, **kwargs):
for_items = copy.deepcopy(validated_data)
# create order object
del validated_data['order_items']
print('VALID', validated_data)
order = Order.objects.create(**validated_data)
# create order items
for item in for_items.pop('order_items'):
order_item = dict(item.items())
print('ITEM', order_item)
OrderItem.objects.create(order=order, **order_item)
return order