【问题标题】:How to filter a Django queryset, after it is modified in a loop在循环中修改后如何过滤 Django 查询集
【发布时间】:2021-10-18 19:03:56
【问题描述】:

我最近一直在使用 Django,这让我很困惑(尽管我也喜欢它)。

我现在面临的问题是,当我在循环时,在修改查询集的循环中,在下一个循环中 .filter 不起作用。

那么让我们来看下面的简化示例:

我有一本由这样的查询集组成的字典 animal_dict = {鸡:6, 奶牛:7, 鱼:1, 羊:2}

查询集被称为self.animals

for key in dict:
    if dict[key] < 3:
        remove_animal = max(dict, key=dict.get)
        remove = self.animals.filter(animal = remove_animal)[-2:]
        self.animals = self.animals.difference(remove)
        key[replaced_industry] = key[replaced_industry] - 2

我正在尝试做的事情如下:我的目标是动物下面需要有一个平衡。因此,由于没有足够的,n 最高的动物中的 2 只必须离开()。然后在第二个循环中 - 由于没有足够的 sheep,因此 n 最高的 2 只动物必须再次走(chicken)。

现在它第一次循环(使用fish)时,.filter 完全按照它应该的方式运行。但是,当我第二次循环它时(对于 sheep),remove = self.animals.filter(animal = remove_animal)[-2:] 给我的输出与animal = 过滤器不一致。当我在第二个循环中打印 remove 时,它会返回所有不同动物的列表(而不仅仅是 1 个)。

循环之后,dict 应该如下所示:{chicken: 4, 奶牛:5, 鱼:1, 羊:2} 这是因为第一头奶牛会下降 2,它是 max,然后鸡会下降 2,然后是 max

我在这里肯定缺少一些 Django 逻辑,但对我来说这似乎很奇怪。我希望这个问题得到了很好的理解,否则很乐意进一步澄清。

【问题讨论】:

  • 请不要使用dict作为变量名,它会覆盖对dict类的引用。至于替换项目,您究竟想要做什么?在循环中创建查询通常不是一个好主意,因为这将导致 很多 往返于数据库。
  • 记住一件事:永远不要在循环中进行 SQL 查询。它是性能杀手。先进行查询,然后使用结果并继续....
  • 所以dict其实不是字典的名字,只是为了更清楚(但我现在改了)我的目标是动物下面需要有一个平衡。因此,由于没有足够的鱼,因此 n 最高的 2 只动物必须离开。然后在第二个循环中 - 因为没有足够的羊,所以 n 最高的 2 只动物必须再去一次

标签: django django-models django-queryset


【解决方案1】:

正如其他人指出的那样,每次调用 self.animals.filter 时,您都是在向数据库发出请求,这不应该在循环中完成。

您要达到的目标不是很清楚,但您似乎希望每种动物的数量(几乎?)相同,并且您可以对其执行的唯一操作是减少动物的数量。

如果可以的话,最好避免循环。

如果你希望它们都是相同的数字,而你只能减少你拥有的动物数量,那么最好的解决方案是

fewest_number = min(self.animals.values())
self.animals = {animal: fewest_number for animal in self.animals.keys()}

如果你想说,允许最小动物的容忍度+1

fewest_number = min(self.animals.values()) + 1
self.animals = {animal: fewest_number for animal in self.animals.keys()}

如果你能增加每种动物的数量,那么你可以找到平均值:

average_number = sum(self.animals.values()) / len(self.animals)
self.animals = {animal: average_number for animal in self.animals.keys()}

【讨论】:

    【解决方案2】:

    在这里回答我自己的问题。显然它不起作用,因为只允许 count()order_by()values()values_list() 和联合查询集的切片。您不能对联合查询集进行过滤,这同样适用于 .difference

    在此处了解更多信息:Django: Filter a Queryset made of unions not working

    因为在第二个循环中它被制成一个联合查询集,所以过滤器功能根本不起作用。奇怪的是,这并没有显示错误,而是根本不会过滤,这使得它难以检测。

    【讨论】:

      猜你喜欢
      • 2016-02-01
      • 2021-05-15
      • 2022-01-24
      • 1970-01-01
      • 2017-12-26
      • 1970-01-01
      • 2020-08-22
      • 2019-04-15
      相关资源
      最近更新 更多