首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在自相关模型中使用prefetch_related

如何在自相关模型中使用prefetch_related
EN

Stack Overflow用户
提问于 2018-02-26 15:30:48
回答 4查看 2.4K关注 0票数 10

我有Menu模型,它的ForeignKey命名父级与自身相关。

如果父菜单为None,则表示此菜单是父菜单,如果它显示另一个菜单对象,则意味着它是父菜单(多对一关系)的子菜单。

这是我的问题,我想得到所有的菜单和它的子菜单使用prefetch_related,我怎么做呢?

注意:我不想让子菜单每次都进入数据库

这是我的模型课

代码语言:javascript
运行
复制
class Menu(models.Model):
    title = models.CharField(max_length=30)
    language = models.ForeignKey(Language)
    parent = models.ForeignKey("self", default=None, blank=True, null=True, related_name="submenus")

这是我的查询

代码语言:javascript
运行
复制
pm2 = Menu.objects.filter(parent=None, language__code=language, menutype=menutype).prefetch_related("submenus").order_by("order")
for p in pm2:
    print(p.title)
    print(p.submenus)

当我打印子菜单时,结果是app.Menu.None

EN

回答 4

Stack Overflow用户

发布于 2018-11-24 00:14:03

您不需要使用prefetch_related,因为这是用于many-to-many关系的,您可以使用select_related

所以你的查询是

代码语言:javascript
运行
复制
pm2 = Menu.objects.filter(
    parent=None, language__code=language, menutype=menutype
).select_related(
    "submenus"
).order_by(
    "order"
)
票数 1
EN

Stack Overflow用户

发布于 2020-03-11 11:37:56

因为您使用的是树(通过使用邻接列表),所以如果您有多个父-子关系级别,那么select_relatedprefetch_related都不能正常工作。相反,你将需要一些材料,使这棵树。

https://pypi.org/project/django-closure-tree/提供了一个构建Postgres视图的框架,它将处理这种类型的构造,并为您提供了一些使查询更简单的工具。

这背后的实际代码非常简单:https://schinckel.net/2016/01/27/django-trees-via-closure-view/

票数 0
EN

Stack Overflow用户

发布于 2020-03-22 07:40:55

当我打印子菜单时,结果是app.Menu.None

之所以会发生这种情况,是因为OP正在打印print(p.submenus),这只是一个RelatedManager。它可以通过检查p.submenus的类型来验证。

代码语言:javascript
运行
复制
# this is what it prints in django 1.11
>>> type(p.submenus)                                                                                                                                                                                                               
django.db.models.fields.related_descriptors.create_reverse_many_to_one_manager.<locals>.RelatedManager

要从m2m关系访问查询集,正确的方法是使用.all()

代码语言:javascript
运行
复制
print(p.submenus.all())
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48991847

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档