Reputation: 135
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
Reputation: 20702
There are multiple ways to solve this, but it generally has little to do with Django itself, because these are business decisions:
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.
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
.
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