zoukankan      html  css  js  c++  java
  • 瀑布流&分类筛选&分页

    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>
  • 相关阅读:
    SPSS-Friedman 秩和检验-非参数检验-K个相关样本检验 案例解析
    SPSS-多重响应-频率和交叉表案例分析(问卷调查分析)
    SPSS--回归-多元线性回归模型案例解析
    深入理解RunLoop
    杂七杂八集合
    单元测试
    笔记
    http断点续传
    iOS性能优化
    群聊协议
  • 原文地址:https://www.cnblogs.com/hgzero/p/13446808.html
Copyright © 2011-2022 走看看