Django: После сохранения заказа и удаления корзины заказ теряет информацию о заказанных товарах
Я хочу, чтобы элементы корзины сохранялись в каждом заказе. Но после удаления корзины "service_items" становится пустым.
Шаги:
- Добавить товары в корзину
- Сохранить заказ
- Удалить корзину
Я думаю, что service_items = models.ManyToManyField(Cart)
вызывает проблему, но я не знаю, как ее решить.
Текущий объект заказа после сохранения:
{
"id": 1,
"customer": {
"id": 1,
"first_name": "Some",
"last_name": "User",
"email": "someuser@gmail.com",
"phone_number": "+817056781234",
"member_date": "2023-01-28T14:38:43.196580Z"
},
"status": false,
"total": "15.00",
"order_date": "2023-01-28T16:05:11.704636Z",
"delivery_date": "2023-01-31T12:52:16.193078Z",
"advance_payment": "9.00",
"payment_method": "cash",
"due_payment": 6.0,
"service_items": []
}
Ожидаемый результат:
{
"id": 1,
"customer": {
"id": 1,
"first_name": "Some",
"last_name": "User",
"email": "someuser@gmail.com",
"phone_number": "+817056781234",
"member_date": "2023-01-28T14:38:43.196580Z"
},
"status": false,
"total": "15.00",
"order_date": "2023-01-28T16:05:11.704636Z",
"delivery_date": "2023-01-31T12:52:16.193078Z",
"advance_payment": "9.00",
"payment_method": "cash",
"due_payment": 6.0,
"service_items": [
{
"id": 1,
"service_item": {
"id": 1,
"item_name": "Black Shirt",
"description": "Half and Full Sleeve Black Shirts.",
"wash_price": "3.00",
"stain_treatment_price": "1.00",
"iron_price": "2.00",
"dry_wash_price": "4.00",
"category": {
"id": 2,
"title": "Shirt"
}
},
"is_wash": false,
"is_stain_treatment": true,
"is_iron": false,
"is_dry_wash": true,
"quantity": 3,
"unit_price": "5.00",
"price": "15.00",
"customer": 1
}
]
}
models.py
class ServiceItem(models.Model):
item_name = models.CharField(max_length=200)
description = models.TextField(null=True)
wash_price = models.DecimalField(max_digits=6, decimal_places=2, null=False, default=0)
stain_treatment_price = models.DecimalField(max_digits=6, decimal_places=2, null=False, default=0)
iron_price = models.DecimalField(max_digits=6, decimal_places=2, null=False, default=0)
dry_wash_price = models.DecimalField(max_digits=6, decimal_places=2, null=False, default=0)
category = models.ForeignKey(Category, on_delete=models.PROTECT)
def __str__(self) -> str:
return self.item_name
class Cart(models.Model):
customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
service_item = models.ForeignKey(ServiceItem, on_delete=models.CASCADE)
is_wash = models.BooleanField(default=False)
is_stain_treatment = models.BooleanField(default=False)
is_iron = models.BooleanField(default=False)
is_dry_wash = models.BooleanField(default=False)
quantity = models.SmallIntegerField()
unit_price = models.DecimalField(max_digits=6, decimal_places=2)
price = models.DecimalField(max_digits=6, decimal_places=2)
class Meta:
unique_together = ('service_item', 'customer')
def __str__(self):
return f'{self.customer} - {self.service_item}'
class Order(models.Model):
customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
service_items = models.ManyToManyField(Cart)
status = models.BooleanField(db_index=True, default=False)
total = models.DecimalField(max_digits=6, decimal_places=2)
order_date = models.DateTimeField(db_index=True, auto_now_add=True)
delivery_date = models.DateTimeField(db_index=True, default=datetime.now() + timedelta(days = 1))
advance_payment = models.DecimalField(max_digits=6, decimal_places=2, default=0)
payment_method = models.CharField(max_length=70, db_index=True, default="cash")
def __str__(self):
return f'{self.customer} - {self.order_date}'
serializers.py
class CartSerializer(serializers.ModelSerializer):
service_item = ServiceItemSerializer(read_only=True)
class Meta:
model = Cart
fields = '__all__'
class OrderSerializer(serializers.ModelSerializer):
due_payment = serializers.SerializerMethodField(method_name='calculate_balance')
service_items = CartSerializer(many=True)
class Meta:
model = Order
fields = ['id', 'customer', 'status', 'total', 'order_date', 'delivery_date',
'advance_payment', 'payment_method', 'due_payment', 'service_items']
depth = 1
def calculate_balance(self, product:Order):
if product.advance_payment > 0:
return Decimal(product.total - product.advance_payment)
else:
return Decimal(product.total)
views.py
Есть ли другой способ реализовать то, что я ожидаю?
models.py
class ServiceItem(models.Model):
item_name = models.CharField(max_length=200)
description = models.TextField(null=True)
wash_price = models.DecimalField(max_digits=6, decimal_places=2, null=False, default=0)
stain_treatment_price = models.DecimalField(max_digits=6, decimal_places=2, null=False, default=0)
iron_price = models.DecimalField(max_digits=6, decimal_places=2, null=False, default=0)
dry_wash_price = models.DecimalField(max_digits=6, decimal_places=2, null=False, default=0)
category = models.ForeignKey(Category, on_delete=models.PROTECT)
def __str__(self) -> str:
return self.item_name
class Cart(models.Model):
customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
service_item = models.ForeignKey(ServiceItem, on_delete=models.CASCADE)
is_wash = models.BooleanField(default=False)
is_stain_treatment = models.BooleanField(default=False)
is_iron = models.BooleanField(default=False)
is_dry_wash = models.BooleanField(default=False)
is_placed = models.BooleanField(default=False)
quantity = models.SmallIntegerField()
unit_price = models.DecimalField(max_digits=6, decimal_places=2)
price = models.DecimalField(max_digits=6, decimal_places=2)
class Meta:
unique_together = ('service_item', 'customer')
def __str__(self):
return f'{self.customer} - {self.service_item}'
class Order(models.Model):
customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
service_items = models.ManyToManyField(Cart)
status = models.BooleanField(db_index=True, default=False)
total = models.DecimalField(max_digits=6, decimal_places=2)
order_date = models.DateTimeField(db_index=True, auto_now_add=True)
delivery_date = models.DateTimeField(db_index=True, default=datetime.now() + timedelta(days = 1))
advance_payment = models.DecimalField(max_digits=6, decimal_places=2, default=0)
payment_method = models.CharField(max_length=70, db_index=True, default="cash")
def __str__(self):
return f'{self.customer} - {self.order_date}'
#views.py