五、分页


返回

5.1 批量插入记录

# 方法一
for i in range(100):
  	Book.objects.create(title='西游记')
# 方法二(推荐)
book_list = []
for i in range(100):
  	obj = Book(title='西游记')
    book_list.append(obj)
Book.objects.bulk_create(book_list)

5.2 批量显示记录

  • views.py

    from django.core.paginator import Paginator, EmptyPage
    # 1、获取所有图书记录
    book_list = Book.objects.all()
    # 2、分页处理,每页显示10条
    paginator = Paginator(book_list, 10)
    # 3、当前页码
    current_page_num = int(request.GET.get('page',1))  # 取不到,设置为1
    try:  # 正常页码
        current_page = paginator.page(current_page_num)
    except EmptyPage as e:  # 错误页码,设置为1
      	current_page = paginator.page(1) 
    # 4、显示的页面总个数:(num * 2) + 1
    num = 3
    if paginator.num_pages > (num * 2) + 1:
        if current_page_num - num <= 0:
            page_range = range(1, (num * 2) + 2)
        elif current_page_num + num > paginator.count:
            page_range = range(paginator.count - (num * 2), paginator.count + 1)
        else:
            page_range = range(current_page_num - num, current_page_num + num + 1)
    else:
        page_range = paginator.page_range
    
    print(paginator.count)  # 数据总数
    print(paginator.num_pages)  # 总页数
    print(paginator.page_range)  # 页码列表:range(1,num_pages+1)
    
  • index.html

    <!-- 3、遍历当前页所有书籍 -->
    {% for book in current_page %}
    		
    {% endfor %}
    
    <!-- 4、上一页 -->
    {% if current_page.has_previous %}
        <li>
            <a href="?page={{ current_page.previous_page_number }}" aria-label="Next">
                <span aria-hidden="true">&laquo;</span>
            </a>
        </li>
    {% else %}
    		<!-- 没有上一页:disabled、javascript:0 -->
        <li class="disabled">
            <a href="javascript:0" aria-label="Next">
                <span aria-hidden="true">&laquo;</span>
            </a>
        </li>
    {% endif %}
    
    <!-- 4、所有分页 -->
    {% for i in page_range %}
        <!-- 当前页:active -->
        {% if current_page_num == i %}
            <li class="active"><a href="?page={{ i }}">{{ i }}</a></li>
        {% else %}
            <li><a href="?page={{ i }}">{{ i }}</a></li>
        {% endif %}
    {% endfor %}
    
    <!-- 4、下一页 -->
    {% if current_page.has_next %}
        <li>
            <a href="?page={{ current_page.next_page_number }}" aria-label="Next">
                <span aria-hidden="true">&raquo;</span>
            </a>
        </li>
    {% else %}
    		<!-- 没有下一页:disabled、javascript:0 -->
        <li class="disabled">
            <a href="javascript:0" aria-label="Next">
                <span aria-hidden="true">&raquo;</span>
            </a>
        </li>
    {% endif %}
    
    <!-- 是否有上一页:current_page.has_previous -->
    <!-- 上一页:current_page.previous_page_number -->
    <!-- 是否有下一页:current_page.has_next -->
    <!-- 下一页:current_page.next_page_number -->
    

5.3 自定义分页器

  • 分页器模块pagination.py

    """
    分页组件
    """
    
    
    class Pagination(object):
        def __init__(self, current_page, all_count, base_url, query_params, per_page=20, pager_page_count=11):
            """
            分页初始化
            :param current_page: 当前页码
            :param all_count: 数据库中总条数
            :param base_url: 基础URL
            :param query_params: QueryDict对象,内部含所有当前URL的原条件
            :param pager_page_count: 页面上最多显示的页码数量
            """
            self.base_url = base_url
            self.query_params = query_params
            self.per_page = per_page
            self.all_count = all_count
            self.pager_page_count = pager_page_count
            pager_count, b = divmod(all_count, per_page)
            if b != 0:
                pager_count += 1
            self.pager_count = pager_count
    
            half_pager_page_count = int(pager_page_count / 2)
            self.half_pager_page_count = half_pager_page_count
    
            # 格式错误的页码或不在范围内的页面,设置为默认值1
            try:
                self.current_page = int(current_page)
                if not (0 < self.current_page <= self.pager_count):
                    raise Exception()
            except Exception as e:
                self.current_page = 1
    
        @property
        def start(self):
            """
            数据获取值起始索引
            :return:
            """
            return (self.current_page - 1) * self.per_page
    
        @property
        def end(self):
            """
            数据获取值结束索引
            :return:
            """
            return self.current_page * self.per_page
    
        def page_html(self):
            """
            生成HTML页码
            :return:
            """
            # 如果数据总页码pager_count<11 pager_page_count
            if self.pager_count < self.pager_page_count:
                pager_start = 1
                pager_end = self.pager_count
            else:
                # 数据页码已经超过11
                # 判断: 如果当前页 <= 5 half_pager_page_count
                if self.current_page <= self.half_pager_page_count:
                    pager_start = 1
                    pager_end = self.pager_page_count
                else:
                    # 如果: 当前页+5 > 总页码
                    if (self.current_page + self.half_pager_page_count) > self.pager_count:
                        pager_end = self.pager_count
                        pager_start = self.pager_count - self.pager_page_count + 1
                    else:
                        pager_start = self.current_page - self.half_pager_page_count
                        pager_end = self.current_page + self.half_pager_page_count
    
            page_list = []
    
            if self.current_page <= 1:
                prev = '<li><a href="javascript: 0;">上一页</a></li>'
            else:
                self.query_params['page'] = self.current_page - 1
                prev = '<li><a href="%s?%s">上一页</a></li>' % (self.base_url, self.query_params.urlencode())
            page_list.append(prev)
    
            for i in range(pager_start, pager_end + 1):
                self.query_params['page'] = i
                if self.current_page == i:
                    tpl = '<li class="active"><a href="%s?%s">%s</a></li>' % (
                        self.base_url, self.query_params.urlencode(), i,)
                else:
                    tpl = '<li><a href="%s?%s">%s</a></li>' % (self.base_url, self.query_params.urlencode(), i,)
                page_list.append(tpl)
    
            if self.current_page >= self.pager_count:
                nex = '<li><a href="javascript: 0;">下一页</a></li>'
            else:
                self.query_params['page'] = self.current_page + 1
                nex = '<li><a href="%s?%s">下一页</a></li>' % (self.base_url, self.query_params.urlencode(),)
            page_list.append(nex)
    
            page_str = "".join(page_list)
            return page_str
    
  • 视图函数调用

    from pagination import Pagination
    
    per_page_count = 10
    
    all_count = self.model_class.objects.all().count()
        query_params = request.GET.copy()
        query_params._mutable = True
    
        pager = Pagination(
          current_page=request.GET.get('page'),
          all_count=all_count,
          base_url=request.path_info,
          query_params=query_params,
          per_page=self.per_page_count,
        )
    
        data_list = self.model_class.objects.all()[pager.start:pager.end]
    
  • html文件加载

    <nav>
        <ul class="pagination">
          	{{ pager.page_html|safe }}
        </ul>
    </nav>
    
  • css样式

    .nav {
        min-width: 980px;
        height: 48px;
        background-color: #2F72AB;
        color: #ffffff;
        line-height: 48px;
        overflow: visible;
        font-size: 12px;
    }
    
    .nav .logo-area {
        width: 220px;
        overflow: hidden;
        height: 48px;
        text-align: center;
        background-color: #1c5a9c;
    }
    
    .nav .logo-area > a {
        color: #ffffff;
        text-decoration: none;
        display: inline-block;
    }
    
    .nav .logo-area .logo {
        height: 37px;
        width: 37px;
        float: left;
        margin: 6px;
        margin-right: 10px;
    }
    
    .nav .left-menu {
        font-size: 13px;
    }
    
    .nav .left-menu .menu-item {
        display: inline-block;
        padding: 0 15px;
        cursor: pointer;
        position: relative;
        color: white;
        text-decoration: none;
    }
    
    .nav .left-menu .menu-item:hover {
        background-color: #337ab7;
    
    }
    
    .nav .left-menu .menu-item .more-info {
        display: none;
        position: absolute;
        top: 48px;
        left: 0;
        border: 1px solid rgba(0, 0, 0, .15);
        -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
        box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
        background-color: #fff;
        color: #333;
        z-index: 1003;
    }
    
    .nav .left-menu .menu-item:hover .more-info {
        display: block;
    }
    
    .nav .left-menu .menu-item .more-info .more-item {
        display: block;
        min-width: 120px;
        padding: 0 15px;
        line-height: 35px;
        text-decoration: none;
        color: #000000;
    
    }
    
    .nav .left-menu .menu-item .more-info .more-item:hover {
        background-color: #f1f0f0;
    }
    
    .nav .right-menu .user-menu {
        padding: 0 8px;
        cursor: pointer;
        color: white;
        text-decoration: none;
    }
    
    .nav .right-menu .user-menu:hover {
        background-color: #337ab7;
    
    }
    
    .nav .right-menu .user-info {
        padding: 0 30px 0 10px;
        height: 48px;
        position: relative;
    }
    
    .nav .right-menu .user-info:hover .avatar {
        background-color: #337ab7;
    }
    
    .nav .right-menu .user-info .avatar {
        display: inline-block;
        padding: 0 10px;
        height: 48px;
    }
    
    .nav .right-menu .user-info .avatar img {
        /* margin-top: 2px;*/
    }
    
    .nav .right-menu .user-info .more-info {
        display: none;
        position: absolute;
        top: 48px;
        right: 20px;
        border: 1px solid rgba(0, 0, 0, .15);
        -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
        box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
        background-color: #fff;
        color: #333;
        z-index: 1002;
    }
    
    .nav .right-menu .user-info:hover .more-info {
        display: block;
    }
    
    .nav .right-menu .user-info .more-info .more-item {
        display: block;
        min-width: 160px;
        padding: 0 15px;
        line-height: 35px;
        text-decoration: none;
        color: #000000;
    
    }
    
    .nav .right-menu .user-info .more-info .more-item:hover {
        background-color: #f1f0f0;
    }
    
返回