我在完成Django官方教程和Django Girls教程后,开始了我的第一个Django博客应用程序。我在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'))
基本上我想为每个帖子类别显示最后5行。上面的代码已经工作了,问题是,当我在模板中循环每个帖子时,当调用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个帖子。我正在使用PostgreSQL。
答案 0 :(得分:1)
您的解决方案已基本完成。
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发布后更新)
答案 1 :(得分:0)
我认为你想要最后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 %}