Django模板中的循环:如何控制循环迭代器?

时间:2011-12-15 09:28:32

标签: django loops django-templates

我正在使用Django来显示帖子列表。每个帖子都有一个'is_public'字段,因此如果一个帖子的'is_public'等于False,则不应该向用户显示。此外,我想在一个页面中显示固定数量的帖子,但这个数字可能会根据视图而改变。

我决定在模板中裁剪查询集,因为一些视图使用相同的模板,在视图中生成它意味着很多重复的代码。

如果用python编写,它应该如下所示:

i=number_of_posts_to_show_in_one_page
while i:
  if qs[i].is_public == True:
    #show qs[i] to the page
    i--

由于django模板不支持while循环和for循环似乎很难控制,有没有办法实现这一点?或者我应该以另一种方式做到这一点?(一个想法是在循环之前裁剪qs)谢谢!

更新

我已经编写了这个模板标签来预处理查询集:

    @register.simple_tag(takes_context=True)
    def pre_process_list(context,list,numbers):
        #if not user.has_perm('admin'):
        context['result_list']=list.filter(is_public=True, is_removed=False)[0:numbers]
        #else:
        #context['result_list']=list[0:numbers]
        return ''

在模板中使用for循环之前,我会将查询集传递给此templage标记,并使用一个简单的for循环来显示其结果。

如果将来我想向管理员展示非公开帖子(尚未确定),我可以写一些像评论的那样的逻辑,并在模板中对它们进行不同的样式设置。

2 个答案:

答案 0 :(得分:3)

{% for post in posts %}
  {% if post.is_public %}
    {{ post }}
  {% endif %}
{% endfor %}

虽然这对于manager来说是一个完美的用例。

你可以写一个过滤公共帖子的简单经理。

class PublicPostManager(models.Manager):
    def get_query_set(self):
        return super(PublicPostManager, self).get_query_set().filter(is_public=True)

然后您将其添加到Post班级:

class Post(models.Model):
    ...
    public = PublicPostManager()

然后,您可以将post.public.all()作为public_posts传递给您的模板并简化您的循环:

{% for post in public_posts %}
   {{ post }}
{% endfor %}

答案 1 :(得分:2)

@arie与经理有一个很好的方法,但你可以轻松地做同样的事情而不写经理:

# View
posts = Post.objects.filter(is_public=True) # or use the manager
# Now, you can either limit the number of posts you send
# posts = posts[:5] (only show five in the view)
return render_to_response('foo.html',{'posts':posts})

# Template
# Or you can do the limits in your template itself:
{% for post in posts|slice:":5" %}
   {{ post }}
{% endfor %}

有关详细信息,请参阅slice filter

但是,由于这是一项常见操作,因此使用django 1.3可以使用class based views自动执行大部分操作。