如何为模板制作可重用的Django页面导航解决方案

时间:2014-08-26 06:43:05

标签: django django-pagination

(这是我在尝试创建页面导航时遇到的这个基本问题,我想出了一个解决方案)

这似乎是一件基本的事情,我无法相信找到一个基本的解决方案是如此困难。

基本上django中的分页非常好,直到您需要在模板中将页面显示为导航。然后你必须创建一些淫秽的逻辑来完成以下

  • 将相邻的x页码显示为当前页码。例如
  • 之前和之后2
  • 确定何时显示第一页码
  • 确定何时显示最后一页编号
  • 突出显示当前页码
  • 根据你想要的样式

对于少量页面,默认分页很好,但只要你有一个重要的数字,就很难达到上述要求。

我发布了一个解决方案,我找到并修改了与django 1.5+一起使用。 如果您有其他解决方案可以分享这个主题,那么很乐意看到它们。 感谢

2 个答案:

答案 0 :(得分:1)

Django为您the basics提供了在模板中使用paginator对象的信息:

{% for contact in contacts %}
    {# Each "contact" is a Contact model object. #}
    {{ contact.full_name|upper }}<br />
    ...
{% endfor %}

<div class="pagination">
    <span class="step-links">
        {% if contacts.has_previous %}
            <a href="?page={{ contacts.previous_page_number }}">previous</a>
        {% endif %}

        <span class="current">
            Page {{ contacts.number }} of {{ contacts.paginator.num_pages }}.
        </span>

        {% if contacts.has_next %}
            <a href="?page={{ contacts.next_page_number }}">next</a>
        {% endif %}
    </span>
</div>

这不包含在标签中的原因可能是因为django不想在你身上强制执行某个样式/库(jquery除外,但即使是可选的)。

进一步决定分页的风格可以是固执的,并且与应用程序和视口不同。但是,还有很多其他人已经解决了这个问题。立即浮现的两个问题是django-endless-paginationdjango-bootstrap-pagination

答案 1 :(得分:1)

实际上,有很多答案在django片段中浮动 我遇到过这篇文章: http://www.tummy.com/articles/django-pagination/

我想要的最终结果。我只需要修改它,以便它可以使用基于通用类的视图,或者至少在相同的上下文变量可用时。

我确信这可以改进,但事实上,我认为这是可以重复使用的。

  1. 首先创建一个新的应用程序。例如my_pagination
  2. 确保此应用已添加到您设置中的INSTALLED_APPS
  3. 在此app文件夹中创建两个文件夹:templatetags和templates
  4. 在templatetags文件夹中创建一个名为paginator.py
  5. 的文件 在模板文件夹中
  6. 创建一个名为(在本例中为my_pagination)的子文件夹,并添加一个名为_paginator.html的文件。 (在文件名前添加下划线是我自己的包含模板文件的约定)
  7. paginator.py

    的代码
    #  Based on: http://www.djangosnippets.org/snippets/73/
    #
    #  Modified by Sean Reifschneider to be smarter about surrounding page
    #  link context.  For usage documentation see:
    #
    #     http://www.tummy.com/Community/Articles/django-pagination/
    
    # modified again by me to include target_url and work with django 1.7
    
    from django import template
    from django.core.paginator import InvalidPage
    
    register = template.Library()
    
    def paginator(context, adjacent_pages=2, target_url=None):
        """
        To be used in conjunction with the object_list generic view.
    
        Adds pagination context variables for use in displaying first, adjacent and
        last page links in addition to those created by the object_list generic
        view.
    
        """
        startPage = max(context['page_obj'].number - adjacent_pages, 1)
        if startPage <= 3: startPage = 1
        endPage = context['page_obj'].number + adjacent_pages + 1
        if endPage >= context['paginator'].num_pages - 1: endPage = context['paginator'].num_pages + 1
        page_numbers = [n for n in range(startPage, endPage) \
                if n > 0 and n <= context['paginator'].num_pages]
        page_obj = context['page_obj']
        paginator = context['paginator']
    
        try:
            previous = context['page_obj'].previous_page_number()
        except InvalidPage:
            previous = None
    
        try:
            next = context['page_obj'].next_page_number()
        except InvalidPage:
            next = None
    
    
        return {
            'page_obj': page_obj,
            'paginator': paginator,
            'page': context['page_obj'].number,
            'page_numbers': page_numbers,
            'next': next,
            'previous': previous,
            'has_next': context['page_obj'].has_next(),
            'has_previous': context['page_obj'].has_previous(),
            'show_first': 1 not in page_numbers,
            # show last if the last page number is not in "page_numbers"
            'show_last': context['paginator'].num_pages not in page_numbers,
            'target_url' : target_url
        }
    
    register.inclusion_tag('my_pagination/_paginator.html', takes_context=True)(paginator)
    

    _paginator.html 的代码可以是您想要的任何内容,只要您了解逻辑(这非常简单) 我使用基础5和fontawesome所以我的_paginator.html看起来像

    <ul class="pagination">
       {% if has_previous %}
       <li class="arrow"><a href="{{ target_url }}?page={{ previous }}" target="_parent"><i class="fa fa-angle-double-left fa-lg fa-fw"></i></a></li>
       {% else %}
       <li class="arrow unavailable"><i class="fa fa-angle-double-left fa-lg fa-fw"></i></li>
       {% endif %}
    
       {% if show_first %}
          <li><a href="{{ target_url }}?page=1" target="_parent">1</a></li>
          <li>...</li>
       {% endif %}
    
       {% for linkpage in page_numbers %}
          {% if linkpage == page %}
              <li class="current">{{ page }}</li>
          {% else %}
             <li><a href="{{ target_url }}?page={{ linkpage }}" target="_parent">{{ linkpage }}</a></li>
          {% endif %}
       {% endfor %}
    
      {% if show_last %}
          <li>...</li>
          <li><a href="{{ target_url }}?page={{ paginator.num_pages }}" target="_parent">{{ paginator.num_pages }}</a></li>
       {% endif %}
       {% if has_next %}
           <li class="arrow"><a href="{{ target_url }}?page={{ next }}" target="_parent"><i class="fa fa-angle-double-right fa-lg fa-fw"></i></a></li>
       {% else %}
          <li class="arrow unavailable"><i class="fa fa-angle-double-right fa-lg fa-fw"></i></li>
       {% endif %}
    </ul>
    

    如何使用 在您的模板文件中,请确保:

    {% load paginator %}
    

    加载自定义模板标记

    然后您希望页面显示在哪里:

    {% paginator 3 %}
    

    备注
    1. target_url只是因为我对iframe有一些奇怪的要求。你可以简单地把这个参数留空 我从原版中拿出了许多参数,因为它们看起来并不相关。