Django Вложенные сериализаторы с внешними полями
Я пытаюсь отправить этот json-запрос через postman
{ "name":"Someones order",
"date_due": "2024-06-23T15:52:59Z",
"customer":3,
"orderItem":[{
"item":1,
"count":1
}]
}
Я реализовал свои модели следующим образом.
class Item(models.Model):
name = models.CharField(max_length=255)
price = models.DecimalField(max_digits=6, decimal_places=2)
bakery = models.ForeignKey(Bakery,on_delete=models.CASCADE,related_name='items')
def __str__(self):
return f'{self.name}'
class Order(models.Model):
name = models.CharField(max_length=255)
bakery = models.ForeignKey(Bakery,on_delete=models.CASCADE,related_name='orders')
customer = models.ForeignKey(Customer,on_delete=models.CASCADE,related_name='orders')
date_created= models.DateTimeField(auto_now_add=True)
date_due = models.DateTimeField()
date_updated = models.DateTimeField(auto_now=True)
#order_item = models.OneToOneField(OrderItem, on_delete=models.CASCADE,related_name='item_orderitems')
def __str__(self):
return f'{self.name}'
class OrderItem(models.Model):
bakery = models.ForeignKey(Bakery,on_delete=models.CASCADE,related_name='order_items')
count = models.IntegerField()
item = models.ForeignKey(Item, on_delete=models.CASCADE,related_name='item_orderitems')
order = models.OneToOneField(Order, on_delete=models.CASCADE,related_name='orderitems')
def __str__(self):
return f'{self.name}'
Сериализатор реализован как
class OrderItemCreateSerializer(serializers.ModelSerializer):
class Meta:
model = OrderItem
fields = ['item','count']
class OrderCreateSerializer(serializers.ModelSerializer):
orderItem=OrderItemCreateSerializer(many=True)
class Meta:
model = Order
fields = ("name","date_due","customer","orderItem")
def create(self, validated_data):
print("create")
print(validated_data)
itemid=validated_data.pop("orderItem")
print(itemid)
bakery=self.context['request'].user.bakery
customer=validated_data.pop("customer")
print(customer)
print("validated_data")
print(validated_data)
order=Order.objects.create(bakery=bakery,customer=customer,**validated_data)
print("create 4")
for items in itemid:
print("create 5")
OrderItem.objects.create(bakery=bakery,order=order,**items)
print("create 6")
print("returning")
return order
Когда я делаю запрос на почту, я получаю
Получили ошибку AttributeError при попытке получить значение для поля orderItem
на сериализаторе OrderCreateSerializer
.
Поле сериализатора может быть названо неверно и не соответствовать какому-либо атрибуту или ключу экземпляра Order
.
Оригинальный текст исключения был: 'Order' object has no attribute 'orderItem'.
Я понимаю, что у Order
модели нет поля, указывающего на orderitem
, но отношение корабля скорее обратное. Но OrderCreateSerializer перечисляет orderItem как поле.
Я реализовал то же самое с обычным сериализатором вместо Modelserializer, думая, что, возможно, он жалуется, поскольку он действительно не является частью модели.
Но самое главное, что если вы посмотрите на мои операторы печати, то они выводят "returning" и возвращаются.
Нужно ли мне реализовать метод create в modelviewset и реализовать там часть логики? Это поможет?
Я бы посоветовал придерживаться возможностей фреймворка. Отношение между Order
и Item
является m2m, так как требуется дополнительное поле, то необходимо создать сквозную таблицу .
models.py
class Order(models.Model):
...
item_list = models.ManyToManyField(
Item,
through="OrderItem",
)
class OrderItem(models.Model):
order = models.ForeignKey(Order, on_delete=models.CASCADE, related_name="items")
item = models.ForeignKey(Item, on_delete=models.CASCADE)
quantity = models.PositiveIntegerField()
serializers.py
class OrderItemSerializer(serializers.ModelSerializer):
class Meta:
model = OrderItem
fields = ["item", "quantity"]
class OrderSerializer(serializers.ModelSerializer):
items = OrderItemSerializer(many=True)
class Meta:
model = Order
fields = ("name", "bakery", "customer", "date_due", "items")
def create(self, validated_data):
items = validated_data.pop("items")
order = super().create(validated_data)
for obj in items:
obj.update({"order": order})
OrderItem.objects.create(**obj)
return order
payload (вы пропустили bakery
ключ:значение)
{
"name": "Someones order",
"date_due": "2024-06-23T15:52:59Z",
"bakery": 1,
"customer": 3,
"items": [
{
"item": 1,
"quantity": 1
}
]
}
И, если у Bakery
нет уникального предмета, то иметь его FK в Item
- пустая трата времени.