Django:在多对多关系中查找所有值,其中相关集合的所有元素都符合特定条件

Posted

技术标签:

【中文标题】Django:在多对多关系中查找所有值,其中相关集合的所有元素都符合特定条件【英文标题】:Django: Find all values in a ManyToMany relationship where all elements of the related set match certain criteria 【发布时间】:2019-07-30 13:12:48 【问题描述】:

我有两个处于多对多关系的模型。我想获得第一个模型的子集,每个相关的模型都匹配某些标准。

场景:这是一个协作字典。一个词可能有 0 个或多个定义。定义可能处于多种状态:“完成”、“进行中”或“已放弃”。我有兴趣找到所有没有定义或只有有“被遗弃”定义的单词。

class DefinitionState(Enum):
    COMPLETE = 0
    IN_PROGRESS = 1
    ABANDONED = 2

class Definition(models.Model):
    text = models.TextField()
    status = models.IntegerField()

class Word(models.Model):
    text = models.CharField(length=60)
    definitions = models.ManyToManyField(Definition, related="words")

spam = Word.objects.create(text="spam")
eggs = Word.objects.create(text="eggs")
bacon = Word.objects.create(text="bacon")
lobster = Word.objects.create(text="lobster")

spam_d1 = Definition.objects.create(
    text="Processed meat", 
    status=DefinitionState.COMPLETE
)
spam_d2 = Definition.objects.create(
    text="Unwanted email",
    status=DefinitionState.ABANDONED
)
spam.definitions.add(spam_d1)
spam.definitions.add(spam_d2)

eggs_d = Definition.objects.create(
    text="Laid by chickens",
    status=DefinitionState.COMPLETE
)
eggs.definitions.add(eggs_d)

bacon_d = Definition.objects.create(
    text="Part of a pig",
    status=DefinitionState.ABANDONED
)
bacon.definitions.add(bacon_d)

所以我有四个字:

spam,有一个 COMPLETE 定义和一个 ABANDONED 定义; eggs,它有一个完整的定义; bacon,有一个 ABANDONED 定义; lobster,没有定义。

我想编写一个返回 (bacon, lobster) 的查询(无特定顺序)。

我可以编写查询返回lobster

Word.objects.annotate(Count("definitions")).filter(definitions__count=0)

我可以确定哪些定义被放弃了:

Definition.objects.filter(status=DefinitionState.ABANDONED)

但我不知道如何询问定义全部被放弃的词。

在此先感谢

【问题讨论】:

【参考方案1】:
Words.objects.exclude(definitions__status__in=[COMPLETE, IN_PROGRESS]) 

【讨论】:

这将包括Word 根本没有定义的对象,否则很好。 预期行为。请参阅上面的“龙虾”示例 你是对的@Nidal。我已经投票赞成你的答案,否则我会再做一次:-) 有时你只见树木不见森林。谢谢@Nidal :) 事实证明,当我将这个解决方案应用到真正的数据库时,它变得真的变慢(超过 20 分钟),其中我有超过 108,000 个定义和超过 119,000 个单词。 1627 需要从查询返回的单词。我最终在 Word 上放置了一个“废弃”的 BooleanField,它将定期更新和/或通过定义上的 post_save 信号进行更新。

以上是关于Django:在多对多关系中查找所有值,其中相关集合的所有元素都符合特定条件的主要内容,如果未能解决你的问题,请参考以下文章

从 Django QuerySet 中获取所有相关的多对多对象

在多对多 SQL 表中查找数据关系或图形

如何在多对多关系 Laravel 中检索所有相关模型?

在多对多关系中选择所有唯一的可能(多个)值?

Django:在多对多关系中交换元素

在多对多关系对象django的对象中获取null