【问题标题】:loop in Django template: how to control the loop iterator?Django模板中的循环:如何控制循环迭代器?
【发布时间】:2012-01-21 00:21:20
【问题描述】:

我正在使用 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循环之前,我会将查询集传递给这个模板标签,并使用一个简单的for循环来显示它的结果。

如果将来我想向管理员显示非公开帖子(尚未决定),我可以编写一些类似于评论的逻辑,并在模板中将它们设置为不同的样式。

【问题讨论】:

  • 你最好在你的视图中构造正确的QuerySet。这样的逻辑属于那里,并且更易于管理。
  • 该模板将被许多视图使用,所以我宁愿不要在这些视图中一次又一次地重复自己。另外,最初我有向管理员展示非公开查询集的想法,这就是为什么我不想事先裁剪查询集。这可能太复杂了,所以没关系

标签: django loops django-templates


【解决方案1】:
{% 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 %}

【讨论】:

    【解决方案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 自动完成大部分操作。

    【讨论】:

      猜你喜欢
      • 2017-10-13
      • 1970-01-01
      • 2012-07-13
      • 1970-01-01
      • 2012-02-16
      • 1970-01-01
      • 2012-07-25
      • 1970-01-01
      相关资源
      最近更新 更多