【问题标题】:Selecting specific fields using select_related in Django在 Django 中使用 select_related 选择特定字段
【发布时间】:2016-06-02 03:28:49
【问题描述】:

我有两个模型文章和博客使用外键相关。我想在提取文章时只选择博客名称。

articles = Articles.objects.all().select_related('blog__name')

生成的查询表明它选择了博客模型中的所有字段。 我尝试将 only() 和 defer() 与 select_related 一起使用,但都没有成功。

articles = Articles.objects.all().select_related('blog__name').only('blog__name', 'title', 'create_time')

上述查询导致错误:select_related 中给出的字段名称无效:选项为:博客

如何生成查询以便只选择文章字段和博客名称?

【问题讨论】:

  • 我认为这不可能——only 的文档没有显示任何遍历关系的示例,而select_related 的文档仅显示了遍历多个关系的示例(即@987654325 @,而不是 rel__field)。似乎你能做的最好的就是articles = Articles.objects.all().select_related('blog').only('blog', 'title', 'create_time')
  • 这样做的目的是什么?性能优化?但是,您可以使用prefetch_related 进行此操作,但这样您最终会得到 2 个查询而不是 1 个。 Articles.objects.all().prefetch_related(Prefetch('blog', queryset=Blog.objects.all().only('name')))
  • 唯一的目的是优化性能。我已经在使用 select_related,但它提供了所有消耗大量内存的属性。有没有其他方法可以做到这一点?
  • 截至目前,对于 django 1.8.9,我无法找到将 'defer' 或 'only' 与 'select_related' 或任何类似返回查询集的解决方案。

标签: django python-2.7 django-queryset django-1.8 django-select-related


【解决方案1】:

select_related 应该在整个模型上使用,然后你可以对其进行更多过滤。这将起作用:

Articles.objects.select_related('blog').only('blog__name', 'title', 'create_time')

【讨论】:

  • 使用 .values 返回字典而不是查询集对象,这使得在模板或视图中使用诸如“file.url”或“file.name”之类的关系毫无用处。有没有其他办法?
  • @RA123 我编辑了我的答案。试过了,这种方式对我有用
  • 这也行不通。我在 Django 1.8 上。它给出了以下错误-“select_related 中给出的字段名称无效:'blog'。选择是:blog” 当我从“only”中的“blog__name”中删除“__name”时,它可以正常工作,但会获取所有字段。
  • 它正在 1.10 上运行,我正在使用它 QuerySet.defer(),谢谢!
【解决方案2】:

您可以为此使用annotate()

>>> a = Articles.objects.annotate(blog_name=F('blog__name')).first()
>>> a.title
>>> a.blog_name

【讨论】:

  • 这不是预期的答案。下面的一个解决了目的。
  • 有时,这可以达到目的。无论如何,两者都很重要
  • 原始问题是:“我如何生成查询以便只选择文章字段和博客名称?”这是从博客中获取所有字段,对吧?如果是这样,它将无法正确回答问题。对吗?
【解决方案3】:

可以通过在only 部分再添加一个字段来完成,它是blog(我认为它有助于 Django 保持对象之间的关系(文章和博客):

articles = Articles.objects.select_related(
    'blog',
).only(
    'blog',
    'blog__name',
    'title',
    'create_time',
)

在 Django==2.2.19 上测试

【讨论】:

    猜你喜欢
    • 2017-01-26
    • 2021-12-23
    • 2019-07-21
    • 2012-01-15
    • 2019-03-09
    • 2012-10-15
    • 2013-08-08
    • 1970-01-01
    • 2021-08-23
    相关资源
    最近更新 更多