namo
namo

Reputation: 135

how to remain the same data after changed or deleted the primary key (an instance)from model

i want to remain the same data as i saved before , after changing , or deleted the model which provide the foreign key ,

i tried to

on_delete=models.SET_NULL

but still removes the instance which i've saved before

class Product(models.Model):
    product_name = models.CharField(unique=True, max_length=50 , 
    blank=False,null=False)
    price = models.PositiveIntegerField()
    active = models.BooleanField(default=True)

    def __str__(self):
        return self.product_name


class Order(models.Model):
    id = models.AutoField(primary_key = True)
    products = models.ManyToManyField(Product ,through='ProductOrder')
    date_time = models.DateTimeField(default=datetime.now()) 


    @property
    def total(self):
        return self.productorder_set.aggregate(
            price_sum=Sum(F('quantity') * F('product__price'), 
            output_field=IntegerField()) )['price_sum'] 


class ProductOrder(models.Model):
    product = models.ForeignKey(Product, on_delete=models.SET_NULL , null=True)
    ordering = models.ForeignKey(Order, on_delete=models.SET_NULL,blank=True,null=True ,default='')
    quantity = models.PositiveIntegerField(default=1)

    def __str__(self):
        return f"{self.product} : {self.quantity}"

and how save the total price in variable , if the the price in Product updated , it remains as the first time ?

and how to prevent losing data from Order model after removing a product from Product model thanks for advice

Upvotes: 0

Views: 245

Answers (1)

dirkgroten
dirkgroten

Reputation: 20702

There are multiple ways to solve this, but it generally has little to do with Django itself, because these are business decisions:

  1. Don't link to the Product in the Order (and ProductOrder) models, but save the product information directly in the ProductOrder model. You could for example use a JSONField (if you're on PostgreSQL) and keep all the product details there, including the price.

  2. Don't change a Product once it's been ordered once. i.e. you can make it impossible to change/delete a Product (on_delete=models.PROTECT). Give a Product a unique SKU and version number, create new versions of your Product when the price changes. That way all orders will use a reference to the Product that was actually ordered. When fetching Products that can be purchased, always fetch the latest version of the Product. You could create a new ProductVersion table for this and link to that instead of the Product.

  3. Don't allow deleting a Product (on_delete=PROTECT), but allow changing the price. Note that if other characteristics of the Product change (such as color), you should always create a new Product. Keep a copy of the paid price in the ProductOrder itself (the line item of the order). This is the most common approach. You just copy the price in the line items, so that you always have actual price paid by the customer.

The solution you choose depends a bit on the business requirements of your company, i.e. how products are managed, what needs to be kept, etc... It also depends on what you want your customers to be able to see when looking up their historical orders.

Upvotes: 2

Related Questions