gpt4 book ai didi

Django:过滤多对多字段时重复

转载 作者:行者123 更新时间:2023-12-04 14:01:52 26 4
gpt4 key购买 nike

我的 Django 应用程序中有以下模型:

class Book(models.Model):
name = models.CharField(max_length=100)
keywords = models.ManyToManyField('Keyword')

class Keyword(models.Model)
name = models.CharField(max_length=100)

我保存了以下关键字:
science-fiction
fiction
history
science
astronomy

在我的网站上,用户可以通过访问 /keyword-slug/ 来按关键字过滤书籍。在我的 View 中,keyword_slug 变量被传递给一个函数,它按关键字过滤 Books,如下所示:
def get_books_by_keyword(keyword_slug):
books = Book.objects.all()
keywords = keyword_slug.split('-')
for k in keywords:
books = books.filter(keywords__name__icontains=k)

这在大多数情况下有效,但是每当我使用包含在关键字表中出现多次的字符串(例如 science-fictionfiction )的关键字进行过滤时,我就会得到同一本书在结果查询集中出现多次。

我知道我可以添加 distinct 来只返回独特的书籍,但我想知道为什么我会从一开始就得到重复,并且真的想了解为什么会这样。由于我只在成功过滤的 QuerySet 上调用 filter(),如何将重复的书添加到结果中?

最佳答案

您示例中的 2 个模型用 3 个表表示: bookkeywordbook_keyword 关系表来管理 M2M 字段。

当您在过滤器调用中使用 keywords__name 时,Django 正在使用 SQL JOIN 来合并所有 3 个表。这允许您通过另一个表中的值过滤第一个表中的对象。

SQL 将是这样的:

SELECT `book`.`id`,
`book`.`name`
FROM `book`
INNER JOIN `book_keyword` ON (`book`.`id` = `book_keyword`.`book_id`)
INNER JOIN `keyword` ON (`book_keyword`.`keyword_id` = `keyword`.`id`)
WHERE (`keyword`.`name` LIKE %fiction%)

加入后你的数据看起来像
| Book Table          | Relation table                     | Keyword table                |
|---------------------|------------------------------------|------------------------------|
| Book ID | Book name | relation_book_id | relation_key_id | Keyword ID | Keyword name |
|---------|-----------|------------------|-----------------|------------|-----------------|
| 1 | Book 1 | 1 | 1 | 1 | Science-fiction |
| 1 | Book 1 | 1 | 2 | 2 | Fiction |
| 2 | Book 2 | 2 | 2 | 2 | Fiction |

然后,当数据从 DB 加载到 Python 时,您只能从 book 表中接收数据。如您所见,第 1 本书在那里重复

这就是多对多关系和 JOIN 的工作原理

关于Django:过滤多对多字段时重复,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18071572/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com