Django 双嵌套序列化器
Django double nested serializer
我正在编写一个 api 的应用程序,其中 Order 是一个提供有关客户想要购买的信息的实体,一个 Order 可以包含具有不同数量和不同价格的不同产品。在订单中包含此信息的实体称为订单详细信息。
我在使用双嵌套序列化程序时遇到了一些问题。
在 post 请求后:
{
"external_id": "PR-123-321-123",
"details": [{
"product": {"id": 4},
"amount": 10,
"price": "12.00"
}, ... ]
}
我想得到这样的回应:
{
"id": 1,
"status": "new",
"created_at": "2021-01-01T00:00:00",
"external_id": "PR-123-321-123",
"details": [{
"id": 1,
"product": {"id": 4, "name": "Dropbox"},
"amount": 10,
"price": "12.00"
}, ... ]
}
但现在我有一些错误:“无法分配“OrderedDict()”:“OrderDetail.product”必须是“Product”实例。“
怎么了?
型号:
from django.db import models
class Order(models.Model):
STATUS_CHOICES = (
('new', 'new'),
('accepted', 'accepted'),
('failed', 'failed')
)
status = models.CharField(max_length=12, choices=STATUS_CHOICES, default='new')
created_at = models.DateTimeField(auto_now_add=True)
external_id = models.CharField(max_length=128, unique=True)
class Product(models.Model):
name = models.CharField(max_length=64)
def __str__(self):
return self.name
class OrderDetail(models.Model):
order = models.ForeignKey(Order, related_name='details', on_delete=models.CASCADE)
amount = models.IntegerField()
product = models.ForeignKey(Product, on_delete=models.CASCADE)
price = models.DecimalField(max_digits=8, decimal_places=2)
def __str__(self):
return f'{self.order} detail'
序列化程序:
from rest_framework import serializers
from rest_framework.serializers import ModelSerializer
from order.models import Order, Product, OrderDetail
class ProductSerializer(ModelSerializer):
class Meta:
model = Product
fields = '__all__'
read_only_fields = ('name', )
class OrderDetailSerializer(ModelSerializer):
product = ProductSerializer()
class Meta:
model = OrderDetail
fields = (
'id',
'product',
'amount',
'price'
)
class OrderSerializer(ModelSerializer):
details = OrderDetailSerializer(many=True)
status = serializers.CharField(source='get_status_display', read_only=True)
class Meta:
model = Order
fields = (
'id',
'status',
'created_at',
'external_id',
'details'
)
def create(self, validated_data):
details_data = validated_data.pop('details')
order = Order.objects.create(**validated_data)
for detail_data in details_data:
OrderDetail.objects.create(**detail_data, order=order)
return order
修改 OrderSerializer 的创建方法,在创建 OrderDetail 对象之前先获取 Product 实例。
class OrderSerializer(ModelSerializer):
details = OrderDetailSerializer(many=True)
status = serializers.CharField(source='get_status_display', read_only=True)
class Meta:
model = Order
fields = (
'id',
'status',
'created_at',
'external_id',
'details'
)
def create(self, validated_data):
details_data = validated_data.pop('details')
order = Order.objects.create(**validated_data)
for detail_data in details_data:
try:
product = Product.objects.get(**detail_data.pop('product'))
OrderDetail.objects.create(**detail_data, order=order, product=product)
except (Product.DoesNotExist, Product.MultipleObjectsReturned):
raise serializers.ValidationError('Your custom error message...')
return order
class OrderSerializer(serializers.ModelSerializer):
order = OrderDetailSerializer(many=True, source='order_set', required=False)
class Meta:
model = Order
fields = (
'id',
'status',
'created_at',
'external_id',
'details'
)
def create(self, validated_data):
if 'order_set' in validated_data:
order = validated_data.pop('order_set')
else:
order = []
instance = super().create(validated_data)
for cd in order:
instance.order_set.create(**cd)
return instance
def create(self, *args, **kwargs):
order = Order.objects.create(external_id=self.context.get('request').data.get('external_id'))
OrderDetail.objects.bulk_create(
[OrderDetail(**order_detail, order=order, product=Product.objects.get(**order_detail.pop('product')))
for order_detail in self.context.get('request').data.get('details')]
)
return order
我正在编写一个 api 的应用程序,其中 Order 是一个提供有关客户想要购买的信息的实体,一个 Order 可以包含具有不同数量和不同价格的不同产品。在订单中包含此信息的实体称为订单详细信息。
我在使用双嵌套序列化程序时遇到了一些问题。
在 post 请求后:
{
"external_id": "PR-123-321-123",
"details": [{
"product": {"id": 4},
"amount": 10,
"price": "12.00"
}, ... ]
}
我想得到这样的回应:
{
"id": 1,
"status": "new",
"created_at": "2021-01-01T00:00:00",
"external_id": "PR-123-321-123",
"details": [{
"id": 1,
"product": {"id": 4, "name": "Dropbox"},
"amount": 10,
"price": "12.00"
}, ... ]
}
但现在我有一些错误:“无法分配“OrderedDict()”:“OrderDetail.product”必须是“Product”实例。“
怎么了?
型号:
from django.db import models
class Order(models.Model):
STATUS_CHOICES = (
('new', 'new'),
('accepted', 'accepted'),
('failed', 'failed')
)
status = models.CharField(max_length=12, choices=STATUS_CHOICES, default='new')
created_at = models.DateTimeField(auto_now_add=True)
external_id = models.CharField(max_length=128, unique=True)
class Product(models.Model):
name = models.CharField(max_length=64)
def __str__(self):
return self.name
class OrderDetail(models.Model):
order = models.ForeignKey(Order, related_name='details', on_delete=models.CASCADE)
amount = models.IntegerField()
product = models.ForeignKey(Product, on_delete=models.CASCADE)
price = models.DecimalField(max_digits=8, decimal_places=2)
def __str__(self):
return f'{self.order} detail'
序列化程序:
from rest_framework import serializers
from rest_framework.serializers import ModelSerializer
from order.models import Order, Product, OrderDetail
class ProductSerializer(ModelSerializer):
class Meta:
model = Product
fields = '__all__'
read_only_fields = ('name', )
class OrderDetailSerializer(ModelSerializer):
product = ProductSerializer()
class Meta:
model = OrderDetail
fields = (
'id',
'product',
'amount',
'price'
)
class OrderSerializer(ModelSerializer):
details = OrderDetailSerializer(many=True)
status = serializers.CharField(source='get_status_display', read_only=True)
class Meta:
model = Order
fields = (
'id',
'status',
'created_at',
'external_id',
'details'
)
def create(self, validated_data):
details_data = validated_data.pop('details')
order = Order.objects.create(**validated_data)
for detail_data in details_data:
OrderDetail.objects.create(**detail_data, order=order)
return order
修改 OrderSerializer 的创建方法,在创建 OrderDetail 对象之前先获取 Product 实例。
class OrderSerializer(ModelSerializer):
details = OrderDetailSerializer(many=True)
status = serializers.CharField(source='get_status_display', read_only=True)
class Meta:
model = Order
fields = (
'id',
'status',
'created_at',
'external_id',
'details'
)
def create(self, validated_data):
details_data = validated_data.pop('details')
order = Order.objects.create(**validated_data)
for detail_data in details_data:
try:
product = Product.objects.get(**detail_data.pop('product'))
OrderDetail.objects.create(**detail_data, order=order, product=product)
except (Product.DoesNotExist, Product.MultipleObjectsReturned):
raise serializers.ValidationError('Your custom error message...')
return order
class OrderSerializer(serializers.ModelSerializer):
order = OrderDetailSerializer(many=True, source='order_set', required=False)
class Meta:
model = Order
fields = (
'id',
'status',
'created_at',
'external_id',
'details'
)
def create(self, validated_data):
if 'order_set' in validated_data:
order = validated_data.pop('order_set')
else:
order = []
instance = super().create(validated_data)
for cd in order:
instance.order_set.create(**cd)
return instance
def create(self, *args, **kwargs):
order = Order.objects.create(external_id=self.context.get('request').data.get('external_id'))
OrderDetail.objects.bulk_create(
[OrderDetail(**order_detail, order=order, product=Product.objects.get(**order_detail.pop('product')))
for order_detail in self.context.get('request').data.get('details')]
)
return order