Django:使用注释将多个模型链接在一起时如何进行计算

时间:2018-08-24 18:59:28

标签: django

我有以下Django模型:

class Ingredient(models.Model):
    name = models.CharField(max_length=200)
    cost_per_kg = models.DecimalField(max_digits=19, decimal_places=10


class Recipe(models.Model):
    name = models.CharField(max_length=200)
    qty_in_kg = models.DecimalField(max_digits=19, decimal_places=10)
    #qty_in_kg quantity of preparation

class RecipeIngredients(models.Model):
    ingredient = models.ForeignKey(Ingredient)
    recipe = models.ForeignKey(Recipe)
    qty_in_kg_of_ing = models.DecimalField(max_digits=19, decimal_places=10)
    #qty_in_kg_of_ing: qty of ingredient in kg required to make the qty_in_kg of recipe

我想获得制作食谱的总费用。

如何获取包含总成本的额外列的食谱查询集。

2 个答案:

答案 0 :(得分:2)

首先,您缺少RecipeIngredient模型中的字段,因为目前RecipeIngredient之间没有任何联系,因此无法收集所有成分给定的Recipe。以下是在recipe中带有外键RecipeIngredient的更新模型,可以解决此问题。

class Ingredient(models.Model):
    name = models.CharField(max_length=200)
    cost_per_kg = models.DecimalField(max_digits=19, decimal_places=10


class Recipe(models.Model):
    name = models.CharField(max_length=200)
    qty_in_kg = models.DecimalField(max_digits=19, decimal_places=10)
    #qty_in_kg quantity of preparation

class RecipeIngredients(models.Model):
    ingredient = models.ForeignKey(Ingredient)
    recipe = models.ForeignKey(Recipe)
    qty_in_kg_rec = models.DecimalField(max_digits=19, decimal_places=10)
    #qty_in_kg_rec: required to make qty_in_kg

您需要运行的脚本如下:

cost = 0
# Loading recipe
recipe = Recipe.objects.get(name="recipe_name")
# Finding every connection between recipe and ingredients
connections = RecipeIngredients.objects.filter(recipe=recipe).all()
for rec_ing in connections:
    # Calculating every ingredient cost
    cost += rec_ing.ingrdient.cost_per_kg * rec_ing.qty_in_kg_rec
# Calculating cost of recipe
cost = cost * recipe.qty_in_kg

答案 1 :(得分:1)

我们可以对其进行如下注释:

from django.db.models import F, Sum

subs = Sum(F('recipeingredients__qty_in_kg_of_ing') *
           F('recipeingredients__ingredient__cost_per_kg'))

qs = Recipe.objects.annotate(
    cost=F('qty_in_kg') * subs
)

这将导致查询如下:

SELECT r.*, (r.qty_in_kg * SUM((ri.qty_in_kg_of_ing * i.cost_per_kg))) AS cost
FROM recipe AS r
LEFT OUTER JOIN recipeingredients AS ri ON r.id = ri.recipe_id
LEFT OUTER JOIN ingredient AS i ON ri.ingredient_id = i.id
GROUP BY r.id

如果食谱中没有成分,则.cost将为None,而不是零。因此,在进一步处理数据时需要考虑到这一点。