django queryset 列表的 "contains" 而非字符串

4 投票
1 回答
2906 浏览
提问于 2025-04-20 13:45

我正在尝试搜索一组段落,这些段落有一个多对多的字段,把每个段落和一个章节联系起来。每个章节都是一本书的一部分,每本书有多个作者,而每个作者可以有多本书,因此也有多个段落。我想从返回的段落中排除一个特定的作者。

简化的模型:

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)

不过,这样做不行,因为“author”是一个单独查询的对象,我无法从中获取,所以这在 Django 中是不合法的。我该如何表达这个意思,同时保持对象作为实际对象,而不是字符串呢?

编辑

如果我运行:

paragraphs.exclude(chapter__book__authors__id = author.id)

这几乎可以工作,但仍然包括一些结果,其中一本书有多个作者,而我想忽略的那个作者也在其中。

1 个回答

0

如果author是一个对象,你可以通过传入author对象的某个字段来实现你想要的效果。

举个例子:

paragraphs.exclude(chapter__book__authors__contains=author.name)

撰写回答