Django: После сохранения заказа и удаления корзины заказ теряет информацию о заказанных товарах

Я хочу, чтобы элементы корзины сохранялись в каждом заказе. Но после удаления корзины "service_items" становится пустым.

Шаги:

  1. Добавить товары в корзину
  2. Сохранить заказ
  3. Удалить корзину

Я думаю, что 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

Вернуться на верх