I want to learn what is the best approach to recalculate a model field value(total_cost
in my Product
model class) in all related models after updating a model. I wrote a piece of code and it works but it takes long time. How can I speed up my code? Here is model classes
#models.py
class Product(..):
total_cost = models.FloatField(...)
materials = models.ManyToManyField(Material, through="MaterialProduct")
def calculate_cost(self):
return round(calc_material_price(self.materialproduct_set.all()),2)
def calc_material_price(self, mylist):
res = 0
for m in mylist:
res += m.material.price * m.material_rate
return res
class Material(..):
price = models.FloatField(...)
class MaterialProduct(..):
product = models.ForeignKey(Product, ..)
material = models.ForeignKey(Material, ..)
material_rate = models.FloatField()
- And my serializer sample
class UpdateProductMaterialSerializer(..):
#...
def update(self, instance, validated_data):
#in front-end total cost calculated and I assign it here directly
instance.total_cost = self.initial_data.get("total_cost")
instance.save()
mylist_data = self.initial_data.get("mylist")
material_list_for_update = []
for item in mylist_data:
material = item.get("material")
material_instance = Material.objects.get(pk=material["id"])
# I use this list for updating all Products
material_list_for_update.append(material_instance)
material_rate = item.get("material_rate")
mp = MaterialProduct.objects.filter(product=instance, material=material_instance).first()
mp.material_rate = material_rate
mp.save()# here my one product is updated successfully
# TO UPDATE ALL PRODUCTS I call below method
# But this takes 15 seconds
update_all_product_by_sent_materials(material_list_for_update)
return instance
def update_all_product_by_sent_materials(self, material_list):
for material in material_list:
for mp in MaterialProduct.objects.filter(material=material):
mp.material.total_cost = mp.material.calculate_cost()
mp.material.save()
- Maybe I should use
total_cost
as property in my Product model class and use it. But I dont know how to approach this problem. - Any help would be appreciated. Thanks in advance