django 分页

2016/5/18 posted in  python

django 分页 pagination

使用django pagination的文档比较多,但是完整整理的还是比较少的,这里完整整理一下使用django pagination的过程。

安装 django pagination

默认的pagination包不包含在django安装包里面的,所以如果直接配置,然后再使用会报找不到pagination类的错误,如下No module named pagination

安装方式 sudo pip install django-pagination.

详情可参考这篇文章

配置分页程序

可以参考官方的pagination文档
也可以参考七步教你实现Django网站列表自动分页

这一步没有什么问题,按照官方指导配置即可。

django 1.9版本报新的错误

django1.9使用django-pageination出现AttributeError错误处理

问题:
在django1.9使用django-pageination出现错误

AttributeError: 'WSGIRequest' object has no attribute 'REQUEST'

原因:
HttpRequest.REQUEST在django1.7中被弃用并使用更明确的HttpRequest.GET和HttpRequest.POST来替代,而在django1.9中HttpRequest.REQUEST被移除了。

处理:

打开python安装目录下的dist-packages_pagination_middleware.py

return int(self.REQUEST['page'])

修改成

return int(self.POST['page'])

遗留一个问题

至此分页已经OK,但是遗留一个分页菜单的问题,光使用{% paginate %} 会报错

TypeError: sequence index must be integer, not 'slice

详细看了一下源码,在下面地方找到问题

...
try:
    paginator = context['paginator']
    page_obj = context['page_obj']
    page_range = paginator.page_range
    # Calculate the record range in the current page for display.
    records = {'first': 1 + (page_obj.number - 1) * paginator.per_page}
    records['last'] = records['first'] + paginator.per_page - 1
    if records['last'] + paginator.orphans >= paginator.count:
        records['last'] = paginator.count
    # First and last are simply the first *n* pages and the last *n* pages,
    # where *n* is the current window size.
    first = set(list(page_range)[:window])
    last = set(list(page_range)[-window:])
    # Now we look around our current page, making sure that we don't wrap
    # around.
    current_start = page_obj.number-1-window
    if current_start < 0:
        current_start = 0
    current_end = page_obj.number-1+window
    if current_end < 0:
        current_end = 0
    current = set(list(page_range)[current_start:current_end])
    pages = []
...

默认的代码是

    first = set(page_range[:window])
    last = set(page_range[-window:])

这个在当前版本是不能执行的,所以修改为上面的就好了。

django 1.9的 paginate。

django 1.9版本用原始的配置发现可以进行分页,但是按页数显示不同的是有问题的,应该是django1.9版本的升级导致的,也暂时没有看源码,直接修改用官方给出的表现方式来配置。

前台代码为:

{% block maincontent %}
    <section class="content">
    
        {% if latest_entry_list %}
            {% for entry in latest_entry_list %}
            
        <article class="post">
            <div class="date-wrapper"> 
                <div class="date-value">{{ entry.publication_date.day }}</div>
                <div class="month-value">{{ entry.publication_date.month }}</div>
            </div>
            <div class="header-wrapper">
                <h2 class="posttitle"><a href="single.html">{{entry.title}}</a></h2>
                <div class="entry-utility">
                    <div class="user">Posted by <a href="#">Templatesquare</a></div> <div class="tag">Tags: <a href="#">Wordpress</a></div>
                </div>
            </div>
            <div class="clear"></div>
            <div class="postimg">
                <img src="{{entry.head_image_url}}" alt="" />
            </div>
   
                                <div class="entry-content">
                {{ entry.blog_abstract }}
                <a href="single.html" class="more">更多&rarr;</a>
            </div>
           
            <div class="clear"></div>
        </article>
            {% endfor %}
        {% endif %}
        
        <div class="wp-pagenavi">
            <span class="step-links">
                <span class="pages">
                    Page {{ latest_entry_list.number }} of {{ latest_entry_list.paginator.num_pages }}
                </span>
                {% if latest_entry_list.has_previous %}
                    <a href="?page={{ latest_entry_list.previous_page_number }}">{% trans 'previous' %}</a>
                {% endif %}
                {% for pagenum in latest_entry_list.paginator.page_range %}
                    {% if pagenum == latest_entry_list.number %}
                        <span class="current"><span>{{ pagenum }}</span></span>
                    {% else %}
                        <a class="page" href="?page={{ pagenum }}">{{ pagenum }}</a>
                        {% endif %}
                {% endfor %}
                {% if latest_entry_list.has_next %}
                    <a href="?page={{ latest_entry_list.next_page_number }}">{% trans 'next' %}</a>
                {% endif %}
            </span>
        </div>
    </section>
{% endblock %}  

后台view代码

def blog(request):
    latest_entry_list = Entry.objects.order_by('creation_date')
    paginator = Paginator(latest_entry_list, 5)
    page = request.GET.get('page')
    
    try:
        entrys = paginator.page(page)
    except PageNotAnInteger:
        entrys = paginator.page(1)
    except EmptyPage:
        entrys = paginator.page(paginator.num_pages)
    context = {'latest_entry_list':entrys}
    
    return render(request, 'blog.html', context)

这样分页就完成了。