每个类别的最后 N 个帖子 SQL 到 ORM
Last N posts per category SQL to ORM
我正在开始我的第一个 Django 博客应用程序 [在完成 Django 官方教程和 Django Girls 教程之后]。我在思考 Django ORM 时遇到了一些麻烦。我有一个有效的 SQL 查询,但我觉得它效率很低,我宁愿在继续之前学习正确的方法。
Post.objects.raw(('SELECT * FROM (SELECT id, category, body, slug, author, title,
published, row_number() OVER (PARTITION BY category) as rownum FROM post) tmp
WHERE rownum < 5'))
基本上我想显示每个 post 类别的最后 5 行。上面的代码已经在工作了,问题是当我在我的模板中循环遍历每个 post 时,当 Post 的 get_absolute_url 正在调用方法。我使用 Django 的 {% url %}
标记修复了此问题,但仍有 7 个额外的查询 运行,我想将其限制为最多 2-3 个。
我有这样一个模型:
class Post(models.Model):
title = models.CharField(max_length=250)
category = models.CharField(max_length=30, choices=CATEGORY_CHOICES)
tags = TaggableManager()
slug = models.SlugField(max_length=250, unique_for_date='published')
author = models.CharField(max_length=50)
body = HTMLField('body')
published = models.DateTimeField(default=timezone.now)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
status = models.CharField(max_length=10, choices=STATUS_CHOICES,
default='draft')
class Meta:
ordering = ('-published',)
db_table = 'post'
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post_detail', args=[self.category, self.slug])
我尝试了几个小时来通过 ORM 让它工作,但无法让它工作。我最终用原始 SQL 完成了它,但我不知道 20 多个额外的查询将是 运行。主要目标是显示按发布日期排序的每个类别的最后 5 post 秒。我正在使用 PostgreSQL.
我想你想要最后 3 个帖子,如果是这样你可以切片
def mayview(request):
last_posts = Post.objects.all().order_by('-created_at')[:3] # list of last posts
return render(request, 'path/to/template', {'last_posts': last_posts})
在您的模板中使用 for 循环解压列表:
{%for post in last_posts%}
<h1>{{post.title}}</h1>
<p>{{post.body}}</p>
<small>{{post.created_by}}</small>
{% endfor %}
您的解决方案即将完成。
from django.db.models.expressions import RawSQL
qs = Post.objects.filter(pk__in=RawSQL(
'SELECT id FROM '
' (SELECT id, '
' row_number() OVER (PARTITION BY category ORDER BY published DESC) as rownum '
' FROM post) tmp '
'WHERE rownum < 5',
[]
)).order_by('category', '-published')
Window functions 可用于 Django 2.0 而不是 RawSQL。 (应该在2.0发布后更新)
我正在开始我的第一个 Django 博客应用程序 [在完成 Django 官方教程和 Django Girls 教程之后]。我在思考 Django ORM 时遇到了一些麻烦。我有一个有效的 SQL 查询,但我觉得它效率很低,我宁愿在继续之前学习正确的方法。
Post.objects.raw(('SELECT * FROM (SELECT id, category, body, slug, author, title,
published, row_number() OVER (PARTITION BY category) as rownum FROM post) tmp
WHERE rownum < 5'))
基本上我想显示每个 post 类别的最后 5 行。上面的代码已经在工作了,问题是当我在我的模板中循环遍历每个 post 时,当 Post 的 get_absolute_url 正在调用方法。我使用 Django 的 {% url %}
标记修复了此问题,但仍有 7 个额外的查询 运行,我想将其限制为最多 2-3 个。
我有这样一个模型:
class Post(models.Model):
title = models.CharField(max_length=250)
category = models.CharField(max_length=30, choices=CATEGORY_CHOICES)
tags = TaggableManager()
slug = models.SlugField(max_length=250, unique_for_date='published')
author = models.CharField(max_length=50)
body = HTMLField('body')
published = models.DateTimeField(default=timezone.now)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
status = models.CharField(max_length=10, choices=STATUS_CHOICES,
default='draft')
class Meta:
ordering = ('-published',)
db_table = 'post'
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post_detail', args=[self.category, self.slug])
我尝试了几个小时来通过 ORM 让它工作,但无法让它工作。我最终用原始 SQL 完成了它,但我不知道 20 多个额外的查询将是 运行。主要目标是显示按发布日期排序的每个类别的最后 5 post 秒。我正在使用 PostgreSQL.
我想你想要最后 3 个帖子,如果是这样你可以切片
def mayview(request):
last_posts = Post.objects.all().order_by('-created_at')[:3] # list of last posts
return render(request, 'path/to/template', {'last_posts': last_posts})
在您的模板中使用 for 循环解压列表:
{%for post in last_posts%}
<h1>{{post.title}}</h1>
<p>{{post.body}}</p>
<small>{{post.created_by}}</small>
{% endfor %}
您的解决方案即将完成。
from django.db.models.expressions import RawSQL
qs = Post.objects.filter(pk__in=RawSQL(
'SELECT id FROM '
' (SELECT id, '
' row_number() OVER (PARTITION BY category ORDER BY published DESC) as rownum '
' FROM post) tmp '
'WHERE rownum < 5',
[]
)).order_by('category', '-published')
Window functions 可用于 Django 2.0 而不是 RawSQL。 (应该在2.0发布后更新)