模板中的 Django 动态对象过滤问题

Posted

技术标签:

【中文标题】模板中的 Django 动态对象过滤问题【英文标题】:Django Dynamic Object Filtering issue in Template 【发布时间】:2020-08-10 05:00:37 【问题描述】:

我有一个页面,其中列出了帖子以及与每个帖子相关的照片。但是,我在从照片列表 QuerySet 过滤和发送照片时遇到问题,因为它在帖子列表查询集的循环下。知道如何运行过滤器以仅将照片作为模板中的相关帖子获取吗?

<h2> Posts: </h2>
% for post in post_list %

     % include 'posts/list-inline.html' with post_whole=post  post_photos=photo_list %

% endfor %

这里需要从 photo_list 中过滤掉与单个帖子有外键关系的多个对象。 QuerySet 过滤器在模板中不起作用。

更新:缩小模型供参考:

class Post(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    post_text = models.CharField(max_length=5000, null=True, blank=True)
    selection = models.ForeignKey(Selection, null=True, blank=False, on_delete=models.SET_NULL)
    timestamp = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)

class PostPhoto(models.Model):
    # to apply multiple photos to same post id
    post_id = models.ForeignKey(Post, null=True, blank=True, on_delete=models.CASCADE)
    photo = models.ImageField(upload_to='img/', blank=True, null=True)
    thumbnail = models.ImageField(upload_to='tmb/', null=True, blank=True, editable=False)

【问题讨论】:

请分享相关模型。 @WillemVanOnsem 我已经编辑并添加了相关模型。 【参考方案1】:

您可以通过以下方式获取相关 PostPhoto 对象的列表:

mypost<b>.postphoto_set.all()</b>

所以在你的模板中,你可以使用:

<h2> Posts: </h2>
% for post in post_list %
     % include 'posts/list-inline.html' with post_whole=post  post_photos=post.postphoto_set.all %
% endfor %

(不带括号,因为模板会自动调用可调用对象)。

为避免 N+1 问题,在视图中,您最好使用.prefetch_related(..) clause [Django-doc] 检索Posts:

posts = Post.objects<b>.prefetch_related('postphoto_set')</b>

【讨论】:

问题是 post_list 包含多个帖子......在这些多个帖子中,每个帖子都有多张照片......所以在这个模板中,我从视图中得到的只是一个 QuerySet post_list 下的多个帖子对象和 photo_list 下多个 PostPhoto 对象的相关 QuerySet。 @Jayesh:在list-inline.html 中,您需要对post_photos 进行迭代,然后逐个渲染这些内容。 哦,我错过了点之前的帖子......它有效......谢谢......虽然我完全不明白你所说的N+1问题...... @Jayesh:如果你渲染 n 个帖子,它会导致 n+1 个查询:一个是获取帖子,一个是 n 获取Post 对象的PostPhotos。通过使用.prefetch_related。 Django 将使用一个额外的查询来获取 all 内存中相关的PhotoPosts,然后在 Django/Python 级别进行连接。因此,您执行两个查询,而不是 n+1 个查询。 从性能的角度来看,这声音非常棒。我现在就试试……

以上是关于模板中的 Django 动态对象过滤问题的主要内容,如果未能解决你的问题,请参考以下文章

如何根据 django 模板中的日期过滤列表

如何在引导选项卡块中按 django 模板中的多对多字段过滤对象

Django:遍历模板中的过滤列表

Django:使用模板中的按钮删除查询过滤器

Django:使用模板中的按钮删除查询过滤器

Django Templates — 将模板中的变量值传递给 templatetags 过滤器