Запрос к моделям django для включения и исключения элементов

В настоящее время у меня есть 2 модели в таком виде

class Recipe(models.Model):
    account = models.ForeignKey(CustomUser, on_delete=models.CASCADE, null=True, blank=True)
    name = models.TextField(null=True, blank=True)
    slug = models.SlugField(null=False, blank=True, unique=True)
    image_path = models.ImageField(upload_to=MEDIA_URL, null=True, blank=True)
    description = models.TextField(null=True, blank=True)
    date_added = models.DateField(auto_now_add=True)

class RecipeIngredients(models.Model):
    recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE, null=True)
    ingredient = models.TextField(null=True, blank=True)
    quantity = models.CharField(max_length=10, null=True, blank=True)
    type = models.CharField(max_length=50, null=True, blank=True)

Я пытаюсь сделать запрос, в котором, если у меня есть список, скажем, из 2 или более элементов, скажем

ingredients = ["egg", "bacon", "rice"]

Чтобы он возвращал мне только те рецепты, в которых точно есть яйцо, бекон и рис, или меньше.

Я смог сделать это халтурным способом, но это очень медленно и, как мне кажется, неправильно использует ORM.

ingredients = ["egg", "bacon", "rice"]
results = []
recipes = []
for i in ingredients:
    r = RecipeIngredients.objects.filter(ingredient__icontains=i)
    results.append(r)
for result in results:
    for r in result:
        recipes.append(r.recipe)
for r in recipes:
    recipeingredients = r.recipeingredients_set.all()
    for ri in recipeingredients:
        ingredient = ri.ingredient
        if ingredient not in ingredients:
            try:
                recipes.remove(r)
            except:
                print(r)
    print("end of recipe")

Любая помощь о том, как сделать этот запрос более правильным, будет принята с благодарностью.

Вы можете использовать сырой sql, что-то вроде этого:

recipe_list = Recipe.objects.raw('select a.*
   from app_Recipe a 
   inner join app_RecipeIngredients b
      on a.id = b.recipe_id and b.ingredient in ("egg", "bacon", "rice")
   group by a.*
   having count(*) >= 2')

можно заменить app_ на название вашего проекта, заменить a.* на список названий столбцов.

Вернуться на верх