цикл в шаблоне Django: как управлять итератором цикла? - PullRequest
2 голосов
/ 15 декабря 2011

Я использую 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, чтобы показать его результат.

Если в будущем я захочу показать непубличные публикации администраторам (что еще не решено), я могу написать в некоторой логике, например, в комментариях, и по-другому оформить их в шаблоне.

Ответы [ 2 ]

3 голосов
/ 15 декабря 2011
{% for post in posts %}
  {% if post.is_public %}
    {{ post }}
  {% endif %}
{% endfor %}

Хотя это было бы идеальным вариантом для менеджера .

Вы можете написать простой менеджер, который фильтрует публичные сообщения.

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 голосов
/ 15 декабря 2011

@ 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 %}

См. фильтр срезов для получения дополнительной информации.

Однако, поскольку это обычная операция, с django 1.3 вы можете использовать представления на основе классов для автоматизации большей части этого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...