关于函数'prefetch_related'的'* lookups'参数的变种

问题描述 投票:1回答:2

我无法弄清楚prefetch_related('arg_set')和prefetch_related('arg')之间的区别。

当使用参数'arg'even'arg_set'有效时,有时prefetch_related不起作用。

我搜索过docs.djangoproject.com,但至少我在下面的两个页面都找不到相关文档。 https://docs.djangoproject.com/en/2.1/ref/models/querysets/ https://docs.djangoproject.com/ja/2.1/ref/contrib/contenttypes/

你们有些人可以详细说明这些差异吗?我想阅读与此问题相关的官方文档,以便向我展示参考链接。

先感谢您。

环境:windows10,python 3.7.2,django 2.1.8,sqlite3,PyCham 2019.1。

views.朋友

from django.shortcuts import render
from .models import Article


def index(request):
    a = Article.objects.all().select_related('user').prefetch_related('comment_set').order_by('id')  # [1]
    a = Article.objects.all().select_related('user').prefetch_related('comment').order_by('id')  # [2]

    return render(request,
                  'sns/index.html',
                  {'articles': a})

models.朋友

from django.db import models
from article_comment_model.settings import AUTH_USER_MODEL


class Article(models.Model):
    user = models.ForeignKey(AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='article_user')
    title = models.CharField(max_length=100)
    text = models.TextField()


class Comment(models.Model):
    user = models.ForeignKey(AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='comment_user')
    article = models.ForeignKey(Article, on_delete=models.CASCADE)
    text = models.TextField()

我想了解各种prefetch_related参数。

django
2个回答
0
投票

callig prefetch_related()的论据将是关系的名称。在你的情况下,这将是一个反向的ForeignKey关系。正如你在documentation中看到的那样,反向关系的名称将是FOO_set,其中FOO是模型的小写名称。

因此在你的例子中prefetch_related('comment_set')应该是正确的。如果你要指定related_name之类的

article = models.ForeignKey(Article, on_delete=models.CASCADE, 
                            related_name='comments')

related_name将被用来代替FOO_set,因此在这种情况下prefetch_related('comments')应该是有效的。


0
投票

prefetch_related中使用的查找名称取决于几个问题的答案:

  • 是您在查询的模型上还是在关系的另一侧定义了关系?

如果在您要查询的模型上定义了关系(由Django文档称为“前向关系”),则查找只是字段名称。如果关系是在关系的另一端定义的(“向后关系”),那么查找取决于第二个问题:

  • 您是否在定义关系的其他模型中定义了related_name

如果是,查找是related_name。如果没有related_name,Django使用默认名称,modelname_set用于x对多关系,modelname用于x对一关系(均为小写)。

实际上,这意味着您的代码中包含以下内容:

  • x对多关系:
# no related names defined, using default manager name
Article.objects.prefetch_related('comment_set')
# using related names
User.objects.prefetch_related('article_user', 'comment_user')
  • x对一关系:
Article.objects.prefetch_related('user')
Comment.objects.prefetch_related('article', 'user')

使用prefetch_related进行x-to-one关系就像上面的最后两个例子一样很少见。我们主要使用select_related,因为后者只在原始查询中创建连接,而不是发出单独的查询。然而,正如你可以读到它的documentation的结尾,prefetch_related有一些潜在的优势。它可以:

  • 获取已过滤的查询集
  • 获取不完整的模型(通过onlydefer
  • 通过Prefetch对象执行嵌套预取
© www.soinside.com 2019 - 2024. All rights reserved.