瀑布流&分类筛选&分页

1. 瀑布流

瀑布流,又称瀑布流式布局。整版以图片为主,大小不一的图片按照一定的规律排列。

是比较流行的一种网站页面布局,视觉表现为参差不齐的多栏布局,随着页面滚动条向下滚动,这种布局还会不断加载数据块并附加至当前尾部。

1.1 models表结构

class Img(models.Model):
    # src = models.CharField(max_length=32, verbose_name='图片路径')
    src = models.FileField(max_length=32, verbose_name='图片路径', upload_to='static/upload')
    title = models.CharField(max_length=16, verbose_name='标题')
    summary = models.CharField(max_length=128, verbose_name='简介')

    class Meta:
        verbose_name_plural = '图片'

    def __str__(self):    # 在admin中显示每个img对象对应的title,否则每个对象都会显示Img object
        return self.title

1.2 views视图函数

from django.http import JsonResponse
def imgs(request):
    if request.method == 'GET':
        return render(request, 'img.html')
    elif request.method == 'POST':
        nid = request.POST.get('nid')
        img_list = models.Img.objects.filter(id__gt=nid).values('id', 'src', 'title')
        img_list = list(img_list)
        ret = {
            'status': True,
            'data': img_list,
        }
        # return HttpResponse(json.dumps(ret))  # 这样也行
        return JsonResponse(ret)

1.3 img.html模板文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .w{
             1000px;
            margin: 0 auto;
        }
        .item{
             25%;
            float: left;
        }
        .item img{
             100%;
        }
    </style>
</head>
<body>
    <div>瀑布流</div>
    <div class="w" id="container">
       <div class="item"></div>
       <div class="item"></div>
       <div class="item"></div>
       <div class="item"></div>
    </div>
<script src="/static/jquery-3.1.1.js"></script>
<script>
    $(function () {
        var obj = new ScrollImg();    // 实例化一个ScrollImg对象, 专门负责瀑布流的执行
        obj.initImg();       // 进行图片的获取和在页面的插入
        obj.scrollEvent();   // 探测滑轮是否滑到底部(当前最后一张图片)
    });
    function ScrollImg() {
        // nid和lastPosition这两个变量被模拟成了类似py类中的静态变量
        this.nid = 0;            // 保存最后一张图片的id号
        this.lastPosition = 3;   // 保存最后一张图片在div中的位置编号(0到3,一共四个div)
        this.initImg = function () {
            var that = this;     // 这里的this指的就是这个实例化的对象(本身) ,// this = obj
                console.log(that.nid);
                $.ajax({
                    url: '/imgs.html',
                    type: 'POST',
                    data: {nid: that.nid, },
                    dataType: 'JSON',
                    success:function (arg) {
                        var img_list = arg.data;
                        $.each(img_list, function (index, v) {
                            var eqv = (index+that.lastPosition+1) % 4;
                            var tag = document.createElement('img');
                            tag.src = v.src;
                            $('#container').children().eq(eqv).append(tag);
                            // 当循环到最后一个图片时,将图片的ID赋值给NID
                            if(index+1==img_list.length){
                                that.nid = v.id;
                                // that.nid = 0;
                                that.lastPosition = eqv;
                            }
                    })
                }
            })
        };
        this.scrollEvent = function () {
            var that = this;
            $(window).scroll(function () {
                // 什么时候到达最底部
                // 文档高度
                var docHeight = $(document).height();
                // 窗口高度
                var winHeight = $(window).height();
                // 滚动条滑动高度
                var scrollTop = $(window).scrollTop();
                if(winHeight+scrollTop == docHeight){
                    // 一旦窗口的高度加上滑轮滑动的距离等于整个图片文档的高度,就再执行一次initImg
                    that.initImg();
                }
            })
        }
    }
</script>
</body>
</html>

1.4 效果展示

2. 分类筛选

2.1 实现的效果

  • 在页面上点击的标签序号将作为URL的参数传递给后端进行处理

1)简单版的实现效果

2)略微复杂的多条件筛选

2.2 models表结构设计

1)设计四张表

  • Direction:方向表,可以有自动化、测试、运维、前端等IT大方向
  • Classification:分类表,可以有Python、Linux、JavaScript、C++等技术
  • Level:等级表,给技术划分具体的级别,可以有初、中、高、骨灰等级别
  • Video:视频表,通过以上等分类选择,筛选出具体的视频内容

2)表与表之间的关系

Direction表和Classification表之间是多对多的关系:某个方向可以对应多种技术,而某个技术也可以包含在多个方向中。

Video表中要定义两个外键,分别与Classification和Level表建立外键关联。

综上,Video表和Classification、Level建立了外键关联,Classification表和Direction表建立了多对多关联。

3)具体在models中的实现

class Direction(models.Model):
    """方向表:自动化,测试,运维,前端"""
    # weight = models.IntegerField(verbose_name="权重(按从大到小排列)", default=0)
    name = models.CharField(verbose_name='名称', max_length=32)
    classification = models.ManyToManyField('Classification')

    class Meta:
        db_table = 'Direction'                # 数据库中生成的表名称 默认 app名称 + 下划线 + 类名
        verbose_name_plural = '方向(视频方向)'  # 设置admin中的表名

    def __str__(self):
        return self.name


class Classification(models.Model):
    """分类表:Python,Linux,JavaScript,OpenStack,Node.js"""
    # weight = models.IntegerField(verbose_name='权重(按从大到小排列)', default=0)
    name = models.CharField(verbose_name='名称', max_length=32)

    class Meta:
        db_table = 'Classification'
        verbose_name_plural = '分类(视频分类)'

    def __str__(self):
        return self.name


class Level(models.Model):
  """级别表"""
    title = models.CharField(max_length=32)

    class Meta:
        verbose_name_plural = '难度级别'

    def __str__(self):
        return self.title


class Video(models.Model):
  """视频表,保存视频的各种信息"""
    status_choice = (
        (1, '下线'),
        (2, '上线'),
    )
    # 视频上下线状态,默认是1, 也就是下线状态
    status = models.IntegerField(verbose_name='状态', choices=status_choice, default=1)
    level = models.ForeignKey(Level, on_delete=models.CASCADE)
    # level = models.IntegerField(verbose_name='级别', choices=level_choice, default=1)
    classification = models.ForeignKey('Classification', null=True, blank=True, on_delete=models.CASCADE)

    weight = models.IntegerField(verbose_name='权重(按从大到小排列)', default=0)

    title = models.CharField(verbose_name='标题', max_length=32)
    summary = models.CharField(verbose_name='简介', max_length=32)
    # img = models.ImageField(verbose_name='图片', upload_to='./static/images/Video/')
    img = models.CharField(verbose_name='图片', max_length=32)
    href = models.CharField(verbose_name='视频地址', max_length=256)

    create_date = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = 'Video'
        verbose_name_plural = '视频'

    def __str__(self):
        return self.title

4)在admin中注册表结构

from django.contrib import admin

from app01 import models

admin.site.register(models.Direction)
admin.site.register(models.Classification)
admin.site.register(models.Level)
admin.site.register(models.Video)

2.3 urls路由设置

  • url中后缀的每个数字都分别对应于一个分类类型
from django.contrib import admin
from django.urls import path

from django.conf.urls import url
from app01 import views
urlpatterns = [
    path('admin/', admin.site.urls),

    url(r'video-(?P<classification_id>(d+))-(?P<level_id>(d+))-(?P<status>(d+)).html$', views.video),   
  # 技术类型、等级、上下线状态

    url(r'video2-(?P<direction_id>(d+))-(?P<classification_id>(d+))-(?P<level_id>(d+)).html$', views.video2, name="video2"),
  # 方向、技术类型、等级
]

2.4 views视图函数中的处理

1)简易版的实现

from django.shortcuts import render, HttpResponse
from app01 import modelsdef video(request, *args, **kwargs):
    condition = {}  # 构造一个查询字典,这里面将保存查询条件
    for k, v in kwargs.items(): # 获取url后面的每个键值对参数的值,就是拿到每个数字
        temp = int(v)           # url中的字符类型,要转换为int类型
        kwargs[k] = temp
        if temp:
            condition[k] = temp

    # 从数据库取出所有的类型、等级、状态
    class_list = models.Classification.objects.all()
    level_list = models.Level.objects.all()
    status_list = list(map(lambda x: {'id': x[0], 'name': x[1]}, models.Video.status_choice))
    # 视频的上下线状态保存的形式:[(1, '下线'), (2, '上线'), ],这里用map函数将其迭代改造成字典的形式

    # 直接传入包含查询条件的字典,这个字典中保存的就是url中的参数键值对
    video_list = models.Video.objects.filter(**condition)

    return render(
        request,
        'video.html',
        {
            'class_list': class_list,
            'level_list': level_list,
            'status_list': status_list,
            'kwargs': kwargs,     # 将url中的参数也传递给模板
            'video_list': video_list,
        }
    )

2)略微复杂的多条件筛选

from django.shortcuts import render, HttpResponse
from app01 import models
def video2(request, *args, **kwargs):
    condition = {}               # 构造一个查询字典
    for k, v in kwargs.items():  # 将url传过来的键值对中的数字转换为int类型
        temp = int(v)
        kwargs[k] = temp

    # 拿到url中对应各个键的值
    direction_id = kwargs.get('direction_id')
    classification_id = kwargs.get('classification_id')
    level_id = kwargs.get('level_id')
    level_list = models.Level.objects.all()

    # 从数据库中拿到所有的方向,因为方向会一直在页面上显示
    direction_list = models.Direction.objects.all()

    # 方向若选了0,也就是全部,则会显示所有的技术类型
    if direction_id == 0:
        class_list = models.Classification.objects.all()
        # 进入技术类型判断的逻辑
        #   如果是0显示全部,本来上上一层逻辑中就是显示全部技术类型,则可以忽略,
        #   如果显示指定的技术类型,则在condition中写入一个查询键值对
        if classification_id == 0:
            pass
        else:
            condition['classification_id'] = classification_id
    # 若用户选择了某个方向(非0),则进入以下逻辑
    else:
        direction_obj = models.Direction.objects.filter(id=direction_id).first()
        class_list = direction_obj.classification.all()

        # 拿到指定某个方向下的所有技术类型的id,以键值对的形式返回
        vlist = direction_obj.classification.all().values_list('id')

        # 构造一个包含某个方向下的所有技术类型id值的列表,若该方向下无技术类型,则该技术类型列表留空
        if not vlist:
            classification_id_list = []
        else:
            classification_id_list = list(zip(*vlist))[0]

        # 若技术类型选择了0(全部),则构造一个包含in关键字的查询条件,查找所有符合条件的技术类型
        if classification_id == 0:
            condition['classification_id__in'] = classification_id_list
        # 若选择了某技术类型,且当前选中的技术类型在某方向的技术类型列表中,则查询条件为查找指定技术类型
        # 否则进入查询全部技术类型的逻辑(也就是选中了某个技术类型,而下一次选择的方向中不包含这个技术类型,)
        else:
            if classification_id in classification_id_list:
                condition['classification_id'] = classification_id
            else:
                # 例如: 指定方向[1,2,3] , 而分类为5时, 就走这里的条件
                kwargs['classification_id'] = 0
                condition['classification_id__in'] = classification_id_list

    # 等级的筛选,选中全部则忽略,否则就加一个查询条件
    if level_id == 0:
        pass
    else:
        condition['level_id'] = level_id

    # 传入构造好的查询字典,到数据库进行筛选,得到包含全部符合条件video的列表
    video_list = models.Video.objects.filter(**condition)

    return render(
        request,
        'video2.html',
        {
            'direction_list': direction_list, # 方向列表
            'class_list': class_list,         # 类型列表
            'level_list': level_list,         # 等级列表
            'video_list': video_list,         # 视频列表
            'kwargs': kwargs,                 # 包含当前url传入参数的列表
        }
    )

2.5 模板文件

1)简易版的video.html模板文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .condition a{
            display: inline-block;
            padding: 5px 8px;
            border: 1px solid #dddddd;
        }
        .condition a.active{
            background-color: coral;
            color: white;
        }
    </style>
</head>
<body>
    <div class="condition">
        <h1>筛选</h1>
        {# 方向的筛选 #}
        <div>
            {# 如果url传入的classification的值等于0,就让改方向类型被选中 #}
            {% if kwargs.classification_id == 0 %}
                <a href="/video-0-{{ kwargs.level_id }}-{{ kwargs.status }}.html" class="active">全部</a>
            {% else %}
                <a href="/video-0-{{ kwargs.level_id }}-{{ kwargs.status }}.html">全部</a>
            {% endif %}
        
            {# 对技术类型进行循环取值,若取出项的值和url中的classification_id的值相等,则让该项被选中 #}
            {% for item in class_list %}
                {% if item.id == kwargs.classification_id %}
                    <a href="/video-{{ item.id }}-{{ kwargs.level_id }}-{{ kwargs.status }}.html" class="active">{{ item.name }}</a>
                {% else %}
                    <a href="/video-{{ item.id }}-{{ kwargs.level_id }}-{{ kwargs.status }}.html">{{ item.name }}</a>
                {% endif %}
            {% endfor %}
        </div>
    
        {# 技术类型的筛选 #}
        <div>
            {% if kwargs.level_id == 0 %}
                <a href="/video-{{ kwargs.classification_id }}-0-{{ kwargs.status }}.html" class="active">全部</a>
            {% else %}
                <a href="/video-{{ kwargs.classification_id }}-0-{{ kwargs.status }}.html">全部</a>
            {% endif %}
            {% for item in level_list %}
               {% if item.id == kwargs.level_id %}
                    <a href="/video-{{ kwargs.classification_id }}-{{ item.id }}-{{ kwargs.status }}.html" class="active">{{ item.title }}</a>
                {% else %}
                    <a href="/video-{{ kwargs.classification_id }}-{{ item.id }}-{{ kwargs.status }}.html">{{ item.title }}</a>
                {% endif %}
            {% endfor %}
        </div>
    
        {# 上下线状态的筛选 #}
        <div>
            {% if kwargs.status == 0 %}
                <a href="/video-{{ kwargs.classification_id }}-{{ kwargs.level_id }}-0.html" class="active">全部</a>
            {% else %}
                <a href="/video-{{ kwargs.classification_id }}-{{ kwargs.level_id }}-0.html">全部</a>
            {% endif %}
            {% for item in status_list %}
                {% if item.id == kwargs.status %}
                    <a class="active" href="/video-{{ kwargs.classification_id }}-{{ kwargs.level_id }}-{{ item.id }}.html">{{ item.name }}</a>
                {% else %}
                    <a href="/video-{{ kwargs.classification_id }}-{{ kwargs.level_id }}-{{ item.id }}.html">{{ item.name }}</a>
                {% endif %} 
            {% endfor %}
        </div>
    </div>
    <div>
        <h1>结果</h1>
        <div>
            {% for row in video_list %}
                <div>{{ row.title }}</div>
            {% endfor %}
        </div>
    </div>
</body>
</html>

2)略微复杂多条件筛选的video2.html模板文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .condition a{
            display: inline-block;
            padding: 5px 8px;
            border: 1px solid #dddddd;
        }
        .condition a.active{
            background-color: coral;
            color: white;
        }
    </style>
</head>
<body>
    <div class="condition">
        <h1>筛选</h1>
        {# 方向的筛选 #}
        <div>
            {% if kwargs.direction_id == 0 %}
                <a href="/video2-0-{{ kwargs.classification_id }}-{{ kwargs.level_id }}.html" class="active">全部</a>
            {% else %}
                <a href="/video2-0-{{ kwargs.classification_id }}-{{ kwargs.level_id }}.html">全部</a>
            {% endif %}
           {% for item in direction_list %}
               {% if item.id == kwargs.direction_id %}
                    <a href="{% url "video2" direction_id=item.id classification_id=kwargs.classification_id level_id=kwargs.level_id %}" class="active">{{ item.name }}</a>
               {% else %}
                   <a href="{% url "video2" direction_id=item.id classification_id=kwargs.classification_id level_id=kwargs.level_id %}">{{ item.name }}</a>
               {% endif %}
           {% endfor %}
        </div>
        {# 技术类型的筛选 #}
        <div>
            {% if kwargs.classification_id == 0 %}
                <a href="/video2-{{ kwargs.direction_id }}-0-{{ kwargs.level_id }}.html" class="active">全部</a>
            {% else %}
                <a href="/video2-{{ kwargs.direction_id }}-0-{{ kwargs.level_id }}.html">全部</a>
            {% endif %}
            {% for item in class_list %}
                {% if item.id == kwargs.classification_id %}
                    <a href="/video2-{{ kwargs.direction_id }}-{{ item.id }}-{{ kwargs.level_id }}.html" class="active">{{ item.name }}</a>
               {% else %}
                   <a href="/video2-{{ kwargs.direction_id }}-{{ item.id }}-{{ kwargs.level_id }}.html">{{ item.name }}</a>
               {% endif %}
            {% endfor %}
        </div>
        {# 等级的筛选 #}
        <div>
            {% if kwargs.level_id == 0 %}
                <a href="/video2-{{ kwargs.direction_id }}-{{ kwargs.classification_id }}-0.html" class="active">全部</a>
            {% else %}
                <a href="/video2-{{ kwargs.direction_id }}-{{ kwargs.classification_id }}-0.html">全部</a>
            {% endif %}
           {% for item in level_list %}
               {% if item.id == kwargs.level_id %}
                    <a href="/video2-{{ kwargs.direction_id }}-{{ kwargs.classification_id }}-{{ item.id }}.html" class="active">{{ item.title }}</a>
               {% else %}
                   <a href="/video2-{{ kwargs.direction_id }}-{{ kwargs.classification_id }}-{{ item.id }}.html">{{ item.title }}</a>
               {% endif %}
           {% endfor %}
        </div>
    </div>
    <div>
        <h1>结果</h1>
        <div>
            {% for row in video_list %}
                <div>{{ row.title }}</div>
            {% endfor %}
        </div>
    </div>
</body>
</html>

3. Django的内置分页

默认的Django内置分页只能实现 【上一页】【下一页】的效果,无法实现显示页码的功能。

实现的效果:

3.1 views.py

from django.shortcuts import render
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger

L = []
for i in range(999):
    L.append(i)

def index(request):
    current_page = request.GET.get('p') # 拿到当前页码

    paginator = Paginator(L, 10)
    # per_page: 每页显示条目数量
    # count:    数据总个数
    # num_pages:总页数
    # page_range:总页数的索引范围,如: (1,10),(1,200)
    # page:     page对象
    try:
        posts = paginator.page(current_page)
        # has_next              是否有下一页
        # next_page_number      下一页页码
        # has_previous          是否有上一页
        # previous_page_number  上一页页码
        # object_list           分页之后的数据列表
        # number                当前页
        # paginator             paginator对象
    except PageNotAnInteger:
        posts = paginator.page(1)
    except EmptyPage:
        posts = paginator.page(paginator.num_pages)
    return render(request, 'index.html', {'posts': posts})

3.2 index.html

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<ul>
    {% for item in posts %}
        <li>{{ item }}</li>
    {% endfor %}
</ul>

<div class="pagination">
      <span class="step-links">
        {% if posts.has_previous %}
            <a href="?p={{ posts.previous_page_number }}">Previous</a>
        {% endif %}
          <span class="current">
            Page {{ posts.number }} of {{ posts.paginator.num_pages }}.
          </span>
          {% if posts.has_next %}
              <a href="?p={{ posts.next_page_number }}">Next</a>
          {% endif %}
      </span>
</div>
</body>
</html>

4. 扩展Django内置分页

将默认的Django内置分页扩展后,就能实现显示页码的效果了。

实现的效果:

4.1 views.py

from django.shortcuts import render
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger

class CustomPaginator(Paginator):
    def __init__(self, current_page, max_pager_num, *args, **kwargs):
        self.current_page = int(current_page)
        self.max_pager_num = max_pager_num
        super(CustomPaginator, self).__init__(*args, **kwargs)

    def page_num_range(self):
        # 当前页面
        # self.current_page
        # 总页数
        # self.num_pages
        # 最多显示的页码个数
        # self.max_pager_num
        print(1)
        if self.num_pages < self.max_pager_num:
            return range(1, self.num_pages + 1)
        print(2)
        part = int(self.max_pager_num / 2)
        if self.current_page - part < 1:
            return range(1, self.max_pager_num + 1)
        print(3)
        if self.current_page + part > self.num_pages:
            return range(self.num_pages + 1 - self.max_pager_num, self.num_pages + 1)
        print(4)
        return range(self.current_page - part, self.current_page + part + 1)

L = []
for i in range(999):
    L.append(i)

def index(request):
    current_page = request.GET.get('p')
    paginator = CustomPaginator(current_page, 11, L, 10)
    # per_page: 每页显示条目数量
    # count:    数据总个数
    # num_pages:总页数
    # page_range:总页数的索引范围,如: (1,10),(1,200)
    # page:     page对象
    try:
        posts = paginator.page(current_page)
        # has_next              是否有下一页
        # next_page_number      下一页页码
        # has_previous          是否有上一页
        # previous_page_number  上一页页码
        # object_list           分页之后的数据列表
        # number                当前页
        # paginator             paginator对象
    except PageNotAnInteger:
        posts = paginator.page(1)
    except EmptyPage:
        posts = paginator.page(paginator.num_pages)
    return render(request, 'index.html', {'posts': posts})

4.2 index.html

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<ul>
    {% for item in posts %}
        <li>{{ item }}</li>
    {% endfor %}
</ul>
<div class="pagination">
<span class="step-links">
    {% if posts.has_previous %}
        <a href="?p={{ posts.previous_page_number }}">Previous</a>
    {% endif %}

    {% for i in posts.paginator.page_num_range %}
        <a href="?p={{ i }}">{{ i }}</a>
    {% endfor %}

    {% if posts.has_next %}
        <a href="?p={{ posts.next_page_number }}">Next</a>
    {% endif %}
</span>
</div>
</body>
</html>

5. 自定义分页

实现的效果:

5.1 自定义分页插件

  • pager.py
class Paginator(object):
    def __init__(self, totalCount, currentPage, perPageItemNum=10, maxPageNum=11):
        """
        totalCount:数据总个数
        currentPage:当前页
        perPageItemNum: 每页显示的行数
        maxPageNum:最多显示的页码个数
        """
        self.total_count = totalCount
        try:
            v = int(currentPage)
            if v <= 0:
                v = 1
            self.current_page = v
        except Exception as e:
            self.current_page = 1
        self.per_page_item_num = perPageItemNum
        self.max_page_num = maxPageNum

    @property
    def start(self):
        """数据切片的起始位置"""
        return (self.current_page-1) * self.per_page_item_num

    @property
    def end(self):
        """数据切片的结束位置"""
        return self.current_page * self.per_page_item_num

    @property
    def num_pages(self):
        """总的页数"""
        a, b = divmod(self.total_count, self.per_page_item_num)
        if b == 0:
            return a
        return a + 1

    def page_num_range(self):
        """页码范围"""
        part = int(self.max_page_num / 2)
        # 总的页数少于默认要显示的页码数
        if self.num_pages < self.max_page_num:
            return range(1, self.num_pages + 1)
        # 当前页码处于第一页的前一半位置
        if self.current_page - part < 1:
            return range(1, self.max_page_num + 1)
        # 当前页码处于最后一页的后一半位置
        if self.current_page + part > self.num_pages:
            return range(self.num_pages - self.max_page_num + 1, self.num_pages + 1)
        return range(self.current_page - part, self.current_page + part + 1)

    def page_str(self):
        """生成所有的页码"""
        # 创建一个保存所有页码的容器
        page_list = []

        # 生成首页和上一页的页码
        first = "<li><a href='?p=1'>首页</a></li>"
        page_list.append(first)
        if self.current_page == 1:
            the_prev = "<li><a href='#'>上一页</a></li>"
        else:
            the_prev = "<li><a href='?p=%s'>上一页</a></li>" % (self.current_page - 1, )
        page_list.append(the_prev)

        # 生成中间所有页的页码
        for i in self.page_num_range():
            if i == self.current_page:
                temp = "<li class='active'><a href='?p=%s'>%s</a></li>" % (i, i, )
            else:
                temp = "<li><a href='?p=%s'>%s</a></li>" % (i, i, )
            page_list.append(temp)

        # 生成下一页和尾页的页码
        if self.current_page == self.num_pages:
            the_next = "<li><a href='#'>下一页</a></li>"
        else:
            the_next = "<li><a href='?p=%s'>下一页</a></li>" % (self.current_page + 1, )
        page_list.append(the_next)
        last = "<li><a href='?p=%s'>尾页</a></li>" % (self.num_pages, )
        page_list.append(last)

        # 列表容器中的各个页码转换为字符串
        result = ''.join(page_list)
        return result

5.2 在后台函数中调用自定义分页插件

  • views.py
user_list = []
for i in range(1, 999):
    temp = {'username': 'root' + str(i), 'age': i, }
    user_list.append(temp)
    
def index(request):
    # 获取当前页码号
    current_page = int(request.GET.get('p'))
    # 导入自定义分页插件
    from app01.pager import Paginator
    # 参数依次为: 数据总个数, 当前页码号, 每页显示的行数, 最多显示的页码个数
    # 后两个参数默认为: 10, 11
    obj = Paginator(999, current_page,)
    # obj对象中可调用的属性(方法):
    #     start       当前页的起始条目索引
    #     end         当前页的结束条目索引
    #     page_str()  生成的所有页码结构和样式
    data_list = user_list[obj.start:obj.end]
    return render(request, 'index.html', {'data': data_list, 'page_obj': obj, })

5.3 模板文件index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7-dist/css/bootstrap.css">
</head>
<body>
        {# 数据内容 #}
        <ul>
            {% for row in data %}
                <li>{{ row.username }} -- {{ row.age }}</li>
            {% endfor %}
        </ul>

        {# 分页的内容 #}
        <ul class="pagination">
            {{ page_obj.page_str|safe }}
        </ul>
</body>
</html>
原文地址:https://www.cnblogs.com/hgzero/p/13446808.html