在Django中优化数据库请求

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

我在Django中具有如下页面视图,设置如下:

    blog = get_object_or_404(Blog, subdomain=extracted.subdomain)
    all_posts = Post.objects.filter(
        blog=blog, publish=True).order_by('-published_date')
    nav = all_posts.filter(is_page=True)
    posts = all_posts.filter(is_page=False)

这将导致DB被访问3次。我试图对此进行优化,使其仅访问数据库一次。以下代码段将调用次数减少到2,但是我敢肯定还有比我不知道的更好的方法。

blog = get_object_or_404(Blog, subdomain=extracted.subdomain)
all_posts = Post.objects.filter(
    blog=blog, publish=True).order_by('-published_date')
nav = []
posts = []
for post in all_posts:
    if post.is_page:
        nav.append(post)
    else:
        posts.append(post)

据我了解,prefetch_relatedselect_related是相反的,我不确定如何在这种情况下实现它们。

我的模型设置如下:

class Blog(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, blank=True)
    title = models.CharField(max_length=200)
    ...

class Post(models.Model):
    blog = models.ForeignKey(
        Blog,
        on_delete=models.CASCADE,
        related_name='post')
    title = models.CharField(max_length=200)
    ...

提前感谢!

编辑:

由于某种原因,它将执行3个DB请求

blog = get_object_or_404(Blog.objects.prefetch_related('post_set'), subdomain=extracted.subdomain)

posts = blog.post_set.filter(publish=True).order_by('-published_date')
django django-models django-orm
1个回答
0
投票

某些事物:

  • 将它们分成两个查询集或列表是一个坏主意。使用模板检查is_page,仅在nav部分或posts部分中呈现它。
  • 优化这样的查询并不是您获得大量性能的地方。您希望摆脱迭代查询集时(因此在for循环中)发生的查询,这是预取和选择相关的目的。

也就是说,要摆脱多余的查询:

posts = Post.objects.filter(
    blog__subdomain=extracted_subdomain, publish=True
).order_by('-published_date')
if not posts:
   raise Http404('no posts for subdomain')

并且确保您可以从帖子访问博客属性,而无需每次迭代查询:

posts = Post.objects.filter(
    blog__subdomain=extracted_subdomain, publish=True
).select_related('blog').order_by('-published_date')
© www.soinside.com 2019 - 2024. All rights reserved.