Reputation: 95
I am trying to sum the cost of the ingredients of a recipe to have the total cost of a recipe. However when I try to access the cost of "ingredients" or "Ingredient.objects.filter(recipe=self)" these objects aren't created even after a manual save to super. I did however notice if I save it through the Django Admin twice the "Ingredient" objects are populated and the cost field is available. So how can I sum up the total cost of recipe cause my way seems not to work properly? Thanks in advance.
class Material(models.Model):
UNITS = [
('kg', 'kg'),
('g', 'gramm'),
('l', 'liter'),
('stk', 'Stuck'),
('dkg', 'deka'),
]
name = models.CharField(max_length=200)
unit = models.CharField(max_length=20, choices=UNITS, default="kg", verbose_name="Einheit")
lieferant = models.ForeignKey(Lieferant,default=1, verbose_name="Lieferant",on_delete=models.CASCADE, null=True)
costpunit = models.FloatField(verbose_name="Stuckpreis")
menge = models.FloatField(default=1,verbose_name="Menge")
costpkg = models.FloatField(editable=False, verbose_name="Kilopreis")
class Meta:
verbose_name_plural = "Materialien"
def __str__(self):
return self.name
def save(self):
if self.unit and (self.unit is not "stk"):
kilogramms = convert_SI(self.menge, self.unit, "kg")
self.costpkg = self.costpunit/kilogramms
super(Material, self).save()
class Recipe(models.Model):
name = models.CharField(max_length=200)
cost = models.FloatField(default=1, editable=False, verbose_name="Kosten")
ingredients = models.ManyToManyField(Material, through='Ingredient')
def __str__(self):
return self.name
def save(self):
x = 0
super(Recipe, self).save()
for ing in Ingredient.objects.filter(recipe=self):
x += ing.cost
self.cost = x
super(Recipe, self).save()
class Ingredient(models.Model):
UNITS = [
('kg', 'kg'),
('g', 'gramm'),
('l', 'liter'),
('stk', 'Stuck'),
('dkg', 'deka'),
]
material = models.ForeignKey(Material, default=1, verbose_name="Material", on_delete=models.CASCADE, null=True)
recipe = models.ForeignKey(Recipe, default=1, verbose_name="Recipe", on_delete=models.CASCADE, null=True)
menge = models.FloatField(verbose_name="Menge")
unit = models.CharField(max_length=20, choices=UNITS, default="kilo", verbose_name="Einheit")
cost = models.FloatField(default=1, editable=False, verbose_name="Kosten")
def __str__(self):
return self.recipe.name + ": " + self.material.name
def save(self):
if self.unit and (self.unit is not "stk"):
kilogramms = convert_SI(self.menge, self.unit, "kg")
self.cost = kilogramms*self.material.costpkg
super(Ingredient, self).save()
Upvotes: 0
Views: 34
Reputation: 95
After some further debugging I found the actual problem it was the way django saves the recipe in admin it first saves the recipe and then the ingredients so the solution was to edit the related_save method of admin.ModelAdmin for recipe and it looks something like this:
class RecipeAdmin(admin.ModelAdmin):
inlines = (IngredientInlineAdmin,)
fields = ('name', 'cost')
readonly_fields = ["cost"]
def save_related(self, request, form, formsets, change):
super(RecipeAdmin, self).save_related(request, form, formsets, change)
# get the recipe from the form
recip = form.instance
recip.cost = 0
# iterate through the saved ingredients
for ingredient in Ingredient.objects.filter(recipe=recip):
# populate the cost field of the recipe
recip.cost += ingredient.cost
print(recip.cost)
# and save the recipe again after the ingredients were saved
recip.save()
Upvotes: 1