在Django查询集中加入以对其进行过滤

时间:2017-06-03 02:27:39

标签: python mysql django

我有两个查询集,我想加入,但我不知道如何继续。 我想根据在每个查询集上创建的两个注释来过滤数据

模型

class Recipe(models.Model):
  name = models.CharField(max_length=50)
  steps = models.ManyToManyField(StepRecipe)

class StepRecipe(models.Model):
  ingredients = models.ManyToManyField(RecipeIngredient)

class RecipeIngredient(models.Model):
  ingredient = models.ForeignKey(Ingredient)

class Ingredient(models.Model):
  name = models.CharField(max_length=50)

步骤中的Queryset

# Example:
# Main queryset
q = Recipe.objects.all()
ingredients = ['salt','oil','flour','tomato']
# This result in all the ingredients necessary
q1 = q.annotate(total=Count('steps__ingredients__ingredient', distinct=True))
# q1 = [{id:1, name: 'salad', total: 5}, {id:2, name: 'pasta', total: 4}]
# This result in the available ingredients. 
# First I filtered the ingredients I have, them I counted them
q2 = q.filter(steps__ingredients__ingredient__name__in=ingredients)
      .annotate(available=Count('steps__ingredients__ingredient',distinct=True))
# q2 = [{id:1, name: 'salad', available: 3}, {id:2, name: 'pasta', available: 4}]

我想加入两个结果,最后按.filter(total=F('sum'))过滤。 过滤后,这将导致仅显示ID为2的对象,因为总计= 4且可用= 4.

我知道我有|运营商。我必须在这一行做点什么:

result = q1 | q2

但每当我这样做时,其中一个注释就会消失(最后一个,在这种情况下是q2注释,available)。有任何想法吗?如果DB可以这样做,我不想迭代它们。

奇怪的是,有时候当我把所有东西放在一行中时,它会经常给我预期的结果。我的印象这可能是一个错误。我认为它以某种方式缓存了结果......

这就是我所做的,并且正确地做了几次:

queryset = Recipe.objects.all()
        .annotate(total=Count('steps__ingredients', distinct=True))
        .filter(steps__ingredients__ingredient__name__in=ingredients)
        .annotate(sum=Count('steps__ingredients', distinct=True))
        .filter(total=F('sum'))

我正在使用MySQL 5.6和Django 1.11

我尝试使用Django 1.11中新增的.intersection(),它也不起作用(我的DB显然不支持)。我考虑过使用.union(),但操作符|发生的事情恰好发生在这个函数上:一个注释消失了。虽然,一个人消失了,我以为我可以看到两次出现的东西并按此过滤。但是......再次,另一个错误!当我试着注释时,我得到了IndexError: list index out of range

如果有一个更好的想法(不是迭代)或一个不需要原始查询的解决方法的好方法,我会很感激。谢谢!

1 个答案:

答案 0 :(得分:1)

这是来自Django的错误,它正在修复https://code.djangoproject.com/ticket/28297

相关问题