bor*_*req 7 python django django-models
我正在为一个简单的论坛创建一个数据库模型。用户应该能够创建话题、添加帖子并在帖子中发布图片。
在一个视图中,我想显示所有线程并且:
我相信这在不执行线程n查询的情况下是不可能的n,所以真正的问题是如何重新设计数据库以使其成为可能。
class Thread(models.Model):
sticky = models.BooleanField()
...
class Post(models.Model):
thread = models.ForeignKey('Thread')
image = models.OneToOneField('Image', null=True, blank=True, default=None)
date = models.DateTimeField()
...
class Image(models.Model):
image = models.ImageField(...)
...
Run Code Online (Sandbox Code Playgroud)
在这一点上,我知道如何计算帖子和图片,但我不知道如何同时获取第一篇帖子。我考虑在Thread模型中添加额外的字段链接到第一个Post.
我的查询迫使我单独下载第一篇文章:
Thread.objects.annotate(
replies=Count('post'),
images=Count('post__image'),
last_reply=Max('post_date')
)
Run Code Online (Sandbox Code Playgroud)
Mat*_*kel 18
您可以使用 aSubquery对最近相关对象的单个字段进行注释:
comments = Comment.objects.filter(
post=OuterRef('pk')
).order_by('-timestamp').values('timestamp')
Post.objects.annotate(
last_comment_time=Subquery(comments[:1])
)
Run Code Online (Sandbox Code Playgroud)
您可以通过这种方式对多个字段进行注释,但这会损害性能(每个相关子查询单独运行,并且针对每一行,这比 N+1 查询更好,但比单个联接更差)。
您可以在单个字段上构建 JSON 对象,然后对其进行注释:
comments = Comment.objects.filter(
post=OuterRef('pk')
).annotate(
data=models.expressions.Func(
models.Value('author'), models.F('author'),
models.Value('timestamp'), models.F('timestamp'),
function='jsonb_build_object',
output_field=JSONField()
),
).order_by('-timestamp').values('data')
Run Code Online (Sandbox Code Playgroud)
(甚至可以将整个对象作为 JSON 获取,然后在 Django 中重新扩展它,但这有点 hacky)。
另一个解决方案可能是单独获取最新的评论,然后将它们与帖子合并:
comments = Comment.objects.filter(
...
).distinct('post').order_by('post', '-timestamp')
posts = Post.objects.filter(...).order_by('pk')
for post, comment in zip(posts, comments):
pass
Run Code Online (Sandbox Code Playgroud)
您需要确保此处的帖子和评论的顺序相同:这些查询是。如果每个帖子都没有评论,这也会失败。
一种解决方法是将评论放入以帖子 ID 为键控的字典中,然后为每个帖子获取匹配的评论。
comments = {
comment.post_id: comment
for comment in Comment.objects.distinct('post').order_by('post', '-timestamp')
}
for post in Post.objects.filter(...):
top_comment = comments.get(post.pk)
# whatever
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5092 次 |
| 最近记录: |