首页 > 解决方案 > Django:返回属于特定模型的多对多关系的不同集合

问题描述

我想要一个返回属于模型 A 中所有条目的所有不同标签的查询。我怀疑通过巧妙的查询和一些过滤是可能的,但我无法解决。我想尽量减少数据库命中。

楷模:

class Tag(models.Model):
    name = models.CharField(max_length = 50,)
    category = models.CharField(max_length = 50, blank=True)

class A(models.Model):
    ...
    tags = models.ManyToManyField(Tag, blank=True)

class B(models.Model):
    ...
    tags = models.ManyToManyField(Tag, blank=True)

在此期间我的解决方案是:

tags = list()

for a in A.objects.all():
     for t in a.tags.all():
         if t not in tags:
             tags.append(t)

是否有一个优雅的解决方案来实现上述功能?

标签: pythondjangodatabase

解决方案


Tag.objects.filter(a__isnull=false).distinct()应该这样做。

这在这里并不最终相关,因为数据库将能够为您完成(我可能记错了上面的一些语法,但如果是这样,它将是可纠正的,这在单个查询中肯定是可行的)但是如果您在在您对不在数据库中的数据进行操作的情况下,您最好使用tags = set()而不是tags = list()- 它会为您管理唯一性,并且比重复测试列表中的成员身份更有效。例如:

tags = set()
for a in some_iterable:
    for t in a.some_function():
        tags.add(t)

这可以浓缩成一个嵌套的生成器表达式,这会更快一些 - 但使用set而不是list关键的变化,所以我保持它与您最初的尝试相似。嵌套的生成器表达式看起来像:

tags = set(t for a in some_iterable for t in a.some_function())

而且,如果您不打算进一步修改tagsfrozenset(t for a in ...)那么养成一个好习惯。


推荐阅读