Django框架下的加強分頁組件

本文經過文章同步功能推送至博客園,顯示排版可能會有所錯誤,請見諒!

描述:Django框架內置了分頁功能,但其只能知足簡單需求,難以實現複雜功能。 html

實現代碼: python

#!/usr/bin/env python3
# -*- coding:utf-8 -*-
__auth__ = 'Song Wei'

from django.utils.safestring import mark_safe
from math import ceil

class Paginator:
    '''自定製分頁功能,支持設置標籤屬性,支持展現頁碼,支持保留其餘GET參數,支持頁面跳轉後元素定位。
    相關可用屬性以下: 
        start   獲取數據起始位置
        end     獲取數據結束位置
        prvePage    上一頁頁碼
        nextPage    下一頁頁碼
        maxPage     總頁碼
        pvreCode    上一頁顯示文字
        nextCode    下一頁顯示文字
        attr        獲取普通標籤屬性
        current_attr    獲取當前頁標籤屬性
        html        生成html標籤 直接用於模板語言
        bootstrap   直接使用bootstrap分頁樣式 須要導入bootstrap
        bootstrap_size  僅使用boostrap時模板生效 可選設置lg(大),sm(小)
        position    支持分頁跳轉後定位至html指定id處
    相關可用方法以下:
        setattr(attr,current_attr=None,inheritance=True)    設置標籤屬性
        '''

    def __init__(self,totalCount,perPage,currentPage=1,pagerNumRange=0,argName='p',kwargs={}):
        ''' totalCount  數據總數量
            perPage     每頁顯示數量
            currentPage    當前頁碼
            pagerNumRange  上一頁/下一頁中間顯示多少條數字頁碼 默認(0)不顯示
            argName     傳遞頁碼的GET參數名 默認爲p
            kwargs      補充其餘GET參數 通常爲空或直接傳入request.GET
        '''
        self.maxPage = ceil(totalCount/perPage)
        try:
            self.currentPage = int(currentPage)
        except:
            self.currentPage = 1
        self.pagerNumRange = self._pager_num_range(pagerNumRange)
        self.argName = argName
        self.kwargs = ''
        for k,v in kwargs.items():
            if k != self.argName:
                self.kwargs += '%s=%s&' % (k,v)
        self.end = self.currentPage * perPage
        self.start = self.end - perPage
        self.prvePage = self.currentPage - 1 if self.currentPage >1 else 1
        self.nextPage = self.currentPage + 1 if self.currentPage < self.maxPage else self.maxPage
        self.pattern = '<a {attr}href="?{kwargs}{argname}={href}">{content}</a> '
        self.attr,self._current_attr = '',''
        self.bootstrap_size = ''
        self.position = ''
        self.pvreCode,self.nextCode = '&laquo;','&raquo;'

    @property
    def current_attr(self):
        '''返回當前頁標籤屬性'''
        if self._current_attr:
            return self._current_attr
        else:
            return self.attr

    def _pager_num_range(self,pager_num_range):
        '''分頁顯示頁碼數字列表'''
        if pager_num_range == 0:
            return []
        else:
            start = int(self.currentPage - (pager_num_range -1) / 2)
            end = int((self.currentPage + (pager_num_range - 1) / 2))
            if start < 1:
                end += 1 - start
                start = 1
                if end > self.maxPage:
                    end = self.maxPage
            if end > self.maxPage:
                start -= end - self.maxPage
                end = self.maxPage
                if start < 1:
                    start = 1
        return range(start,end+1)

    def setattr(self,attr,current_attr=None,inheritance=True):
        '''設置標籤屬性
            attr    普通標籤屬性
            current_attr    爲當前頁設置額外的屬性
            inheritance     當前頁屬性是否繼承普通標籤屬性'''
        self.attr = ''
        for k,v in attr.items():
            self.attr += '%s="%s" ' % (k,v)
        if current_attr:
            self._current_attr = ''
            if inheritance:
                for k,v in attr.items():
                    if k in current_attr:
                        self._current_attr += '%s="%s" ' % (k, current_attr[k])
                    else:
                        self._current_attr += '%s="%s" ' % (k, v)
                for k in current_attr.keys() - attr.keys():
                    self._current_attr += '%s="%s" ' % (k, current_attr[k])
            else:
                for k,v in current_attr.items():
                    self._current_attr += '%s="%s" ' % (k, v)

    @property
    def html(self):
        '''生成html'''
        pagelist = ''
        position = '#' + self.position if self.position else ''
        if self.currentPage > 1:
            pagelist = self.pattern.format(attr=self.attr,href=str(self.prvePage) + position,
                                           kwargs=self.kwargs,argname=self.argName,content=self.pvreCode)
        for r in self.pagerNumRange:
            if r == self.currentPage:
                pagelist += self.pattern.format(attr=self.current_attr, href=str(r) + position,
                                                kwargs=self.kwargs, argname=self.argName,content=r)
            else:
                pagelist += self.pattern.format(attr=self.attr,href=str(r) + position,
                                                kwargs=self.kwargs, argname=self.argName,content=r)
        if self.currentPage < self.maxPage:
            pagelist += self.pattern.format(attr=self.attr,href=str(self.nextPage) + position,
                                            kwargs=self.kwargs, argname=self.argName,content=self.nextCode)
        return mark_safe(pagelist)

    @property
    def bootstrap(self):
        '直接使用bootstrap樣式'
        html = '''
        <nav aria-label="Page navigation">
          <ul class="pagination">
            {pages}
          </ul>
        </nav>
        '''
        Previous = '''
            <li {disable}>
              <a href="{prvePage}" aria-label="Previous">
                <span aria-hidden="true">%s</span>
              </a>
            </li>
        ''' % self.pvreCode
        Next = '''
            <li {disable}>
              <a href="{nextPage}" aria-label="Next">
                <span aria-hidden="true">%s</span>
              </a>
            </li>
        ''' % self.nextCode
        pagelist = ''
        position = '#' + self.position if self.position else ''
        for r in self.pagerNumRange:
            if r == self.currentPage:
                pagelist += '<li class="active"><a href="?%s%s=%s%s">%s<span class="sr-only">(current)</span></a></li>' % (self.kwargs,self.argname,r,position, r)
            else:
                pagelist += '<li><a href="?%s%s=%s%s">%s</a></li>' % (self.kwargs,self.argName,r,position,r)
        if self.bootstrap_size in ('lg','sm'):
            html = html.replace('pagination','pagination pagination-%s' % self.bootstrap_size)
        if self.currentPage > 1:
            Previous = Previous.format(prvePage='?%s%s=%s' % (self.kwargs,self.argName,self.prvePage) + position,disable='')
        else:
            Previous = Previous.format(prvePage='#', disable='class="disabled"')
        if self.currentPage < self.maxPage:
            Next = Next.format(nextPage='?%s%s=%s' % (self.kwargs,self.argName,self.nextPage) + position,disable='')
        else:
            Next = Next.format(nextPage='#', disable='class="disabled"')
        return mark_safe(html.format(pages=Previous+pagelist+Next))

調用實例: web

在views.py中 django

page = Paginator(len(USER_LIST),15,p,7,'p',request.GET) bootstrap

page.setattr(attr={'class':'btn btn-default'}, current_attr={'class':'btn btn-default active'}) 框架

page.size = 'lg' spa

return render(request,'web/index.html', {'PAGE':page, 'USER_LIST':USER_LIST[page.start:page.end]}) code

在模板tempaltes中 orm

{{ PAGE.html }} 或者 {{ PAGE.bootstrap }} htm

bootstrap是直接使用bootstrap分頁樣式,無需過多設置,而html方法則能夠經過設置Paginator屬性等方式,靈活多變。

相關文章
相關標籤/搜索