django queryset“包含”列表,而不是字符串

Posted

技术标签:

【中文标题】django queryset“包含”列表,而不是字符串【英文标题】:django queryset "contains" for lists, not strings 【发布时间】:2014-11-02 06:46:06 【问题描述】:

我正在尝试搜索具有将每个段落映射到章节的多对多字段的段落查询集。每一章都是一本书的一部分,每一章都有多个作者,每个作者可以有多本书,因此也可以有段落。我想从返回的段落查询集中排除特定作者。

简化模型:

class Paragraph(models.Model):
    id = models.AutoField(primary_key = True)
    chapter = models.ForeignKey(Chapter, related_name = 'paragraphs')

class Chapter(models.Model):
    id = models.AutoField(primary_key = True)
    book = models.ForeignKey(Book, related_name = 'chapters')

class Book(models.Model):
    id = models.AutoField(primary_key = True)
    authors = models.ManyToManyField(User, related_name = 'books')

首先我尝试过:

paragraphs.exclude(chapter__book__authors__contains = author)

这不起作用,因为 author 是一个对象,而不是一个字符串。我可以在 Python 中手动执行此操作:

[p for p in paragraphs if author not in p.chapter.book.authors.filter()]

但这比 QuerySet 方式慢得多。我真正想说的是:

paragraphs.exclude(author__in = chapter__book__authors)

但是,这不起作用,因为“作者”是一个单独查询的对象,我无法从中获取,所以它不是有效的 Django。我该如何表达这一点,将对象保留为实际对象而不是字符串?

编辑

如果我跑了

paragraphs.exclude(chapter__book__authors__id = author.id)

它几乎可以工作,但仍然包括一本书有多个作者且其中一个作者是我想忽略的结果。

【问题讨论】:

你能添加你的模型吗? 编辑中的行不需要 id(可以是 paragraphs.exclude(chapter__book__authors=author))。这不会改变结果,而且它似乎在快速测试中起作用,但也许我做错了什么。你能举一个失败的段落、章节、书籍和作者组合的最小例子吗? 【参考方案1】:

如果author 是一个对象,您应该能够通过传入author 对象的字段来实现您想要的。

例如

paragraphs.exclude(chapter__book__authors__contains=author.name)

【讨论】:

我认为这行不通,因为它必须将作者对象(或它的 id)与名称进行比较。 paragraphs.exclude(chapter__book__authors__id=author.id) 应该可以工作。 正如 Schillingt 所指出的,这会引发错误“相关字段的查找无效:​​包含”,因为每个作者都是一个对象。 @schillingt 您的评论似乎应该有效,但是当我尝试时它没有过滤任何内容。

以上是关于django queryset“包含”列表,而不是字符串的主要内容,如果未能解决你的问题,请参考以下文章

Django queryset values_list 是不是返回一个列表对象?

django queryset 返回“类名对象”而不是 DB 值

Django查询集QuerySet及两大特性

查询集 QuerySet

获取外部对象而不是 ID 列表的 QuerySet

在Django QuerySet上计算vs len