我正在使用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循环来显示其结果。
如果将来我想向管理员展示非公开帖子(尚未确定),我可以写一些像评论的那样的逻辑,并在模板中对它们进行不同的样式设置。
答案 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自动执行大部分操作。