Django个人博客开发之分页与Vue分页

分页介绍与逻辑

由于当前开发的需求当中各种管理平台的增多,各种各样的列表需求逐渐增多,而往往数据量有很多,很难实现也没有必要将所有的数据都罗列到一个前端页面上,用户用不到,也很浪费资源。所以我们有了分页的需求,将数据分页显示。
现在有1000条文章的数据需要展示在我们的计算机上。
1. 可以将1000条分为每10条一页,这样就形成了分页。我们来看一下分页的逻辑:

页码 数据
1 0 - 9
2 10 - 19
3 20 - 29
...... ......
n (n-1)*10 - n*10-1

那么这种分页,需要我们定义当前页码还有单页数据长度。

2. 这样的分页,每次请求,都需要对1000条数据进行遍历,也许浏览者只需要第20条数据,所以,我们是不是可以在上面的基础上,对使用者进行”欺诈”呢?

分页码 页码 数据
0 - 29 1 0 - 9
2 10 - 19
3 20 - 29
30 - 59 4 30 - 39
5 40 - 49
6 50 - 59

这种逻辑,当用户请求数据,先不去查询所有数据,而是查询前30条数据,然后,对这30条数据进行分页,如果有人查询到第4页,我们就接着加载。

到这里,分页的逻辑并没有结束,还需要想明白前端除了分页的数据,还需要什么:

  1. 分页的数据
  2. 当前的页面 用来搭建上一页和下一页
  3. 页码的序列

Vue介绍

上面我们了解了基本的分页,我们今天主要用ajax+vue实现分页的动态加载。当然在这里先需要给大家介绍一下我们的vue.js, 是一套构建用户界面的渐进式框架。只关注视图层的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。

MVC (Model – View - Control)模式

Django个人博客开发之分页与Vue分页_第1张图片

MTV (Model – Template - Views)模式

Django个人博客开发之分页与Vue分页_第2张图片

Vue.js采用的是MVVM(ModelView-viewModel)

强调前端的双向绑定逻辑

通俗的讲,vue.js可以将我们从后端传递过来的json数据传递到HTML当中,进行动态的更新。

首先可以从vue的官网(https://vuejs.org/)上下载vue的脚本,在这里,我们使用已经下载好的文件,将他们放入static下面。




    
    vuejsExample
    
    


    

这个是我们vuejs的测试页面

{% verbatim myblock %}

基本的文本绑定

hello world I am {{ name }}

{% endverbatim myblock %}

效果如下:

Django个人博客开发之分页与Vue分页_第3张图片

这个是vue最基础的例子,在这里我们要注意一下几个点:

{% verbatim myblock %}
    

基本的文本绑定:

hello world I am {{ name }}

{% endverbatim myblock %}
vue对象在HTML当中调用,在js当中进行数据的声明,其中有一些固定的点和结构需要记忆。首先需要声明vue对象,指定绑定的HTML标签,选择器是jq选择器,这里用#veuExample来绑定。具体的数据都放在一个data的地方
{% verbatim myblock %}
    

基本的文本绑定:

hello world I am {{ name }}

{% endverbatim myblock %}

上面是一个最简单的文本绑定的例子,我们接下来再看几种绑定




    
    vuejsExample
    
    


    

这个是我们vuejs的测试页面

{% verbatim myblock %}

基本的循环绑定

hello world I like {{ p }}

{% endverbatim myblock %}

效果如下:

Django个人博客开发之分页与Vue分页_第4张图片

带有属性和映射的循环绑定




    
    vuejsExample
    
    


    

这个是我们vuejs的测试页面

{% verbatim myblock %}

带有属性和映射的循环绑定

  • {{ p.name }}
{% endverbatim myblock %}

效果如下:

Django个人博客开发之分页与Vue分页_第5张图片

基本的事件绑定




    
    vuejsExample
    
    


    

这个是我们vuejs的测试页面

{% verbatim myblock %}

基本的事件绑定

按我呀!
{% endverbatim myblock %}

效果如下:

Django个人博客开发之分页与Vue分页_第6张图片

基于Vue尝试分页

Vue后台数据返回

/OurBlog/Aritcles/views.py

from Article.models import Article
from django.core.paginator import Paginator
from django.http import JsonResponse

def vuePageData(request):
    """
    提供分页的ajax数据
    """
    if request.method == "GET": #如果是get请求
        page = request.GET.get("page") #尝试获取page
        if not page: #默认page 为1
            page = 1
        else:
            page = int(page) #get过来的page参数是字符串
        aritcles = Article.objects.all() #查询所有的数据
        paginator = Paginator(aritcles,3) #对数据进行分页,每页三条
        pageData = paginator.page(page) #获取具体页的数据
        page_data = [] #对数据进行json结构化,json只接受字典对象
        for data in pageData:
            classify = data.classify.all() #多对多字段需要首先查询出所有对应的字段,查询出来还是数据库对象
            if classify:
                classify = [i.label for i in classify] #对字段取指定的lable
            else:
                classify = "" #空类表不可以建json序列,所以,我们改完字符串
            page_data.append(
                {
                    "title": data.title,
                    "author": data.author.name, #w外键,必须调用具体的字段
                    "time": data.time,
                    "description": data.description,
                    "picture": data.picture.name, #这里的name是由于文件对象有name属性
                    "classify": classify,
                    "id": data.id
                }
            )
        result = {
            "pageData": page_data
        }
        return JsonResponse(result)

效果如下:

Django个人博客开发之分页与Vue分页_第7张图片

Html前端进行调用

/OurBlog/template/myArticle.html

{% extends "base.html" %}

{% block title %}
    我的博客
{% endblock %}

{% block style %}



{% endblock %}

{% block content %}

您现在的位置是:网站首页>>个人日记个人日记

{% verbatim myblock %}
  • {% endverbatim myblock %}
    页次:1/1 每页25 总数10首页上一页下一页尾页
    {% endblock %}

    这里我已经提前在admin后台管理中对article进行了添加,所以看到的效果如下:

    Django个人博客开发之分页与Vue分页_第8张图片

    基于vue-resource尝试分页

    上面的逻辑虽然可以实现分页,但是有数据损耗。所以我们主要来实现第二种分页,我们着重看的是分页的后端逻辑

    我们先来查看分页的逻辑

    分页码 页码 数据
    1 1 0 - 3             0,1,2
    2 3 - 6             3,4 ,5
    3 6 - 9              6,7,8
    2 4 9 - 12            9,10,11
    5 12 - 15          12,13,14
    6 15 - 18          15,16,17

    每次查询,查询3页。每页查询 3条。当收到单页码请求:我们只查询9条

    首先完成第一步逻辑

    1,2,3 --> 1

     4,5,6 --> 2

    select_page = 3 #每次3页
    page_num = 3 #每页3条
    select_num = select_page*page_num #单次查询9条
    resutl_dict = {}
    
    query_num = page/page_num #获取查询序列号
    if query_num == int(query_num): #如果整除
        query_num = int(query_num)  #返回整形数
    else: #否则
        query_num = int(query_num)+1 #返回整形数加1
    

    首先完成第二步逻辑

    1  查询 0-9

    2  查询 9-18

    所以

    n  查询 (n-1)*9-n*9

    start = (query_num - 1)*select_num
    end = query_num*select_num
    

    然后,我们需要了解一个原理

    Django模型的查询返回的对象是quertset对象,之后我们需要重写该对象,但是现在我们需要知道这种查询有惰性。

    articels = Article.objects.all() #现在当前查询不会执行,直到调用

    Good

    articels = Article.objects.all()[start:end] #现在当前查询不会执行,直到调用,当前写法的查询效率和数据库limit语句相似

    Bad

    articels = Article.objects.all() #现在当前查询不会执行,直到调用,当前写法的查询效率和数据库limit语句相似
    articles = articels[start:end]

    然后我们查看完整的分页逻辑代码

    def vuePageData1(request):
        """
        第二种分页的视图函数
        """
        if request.method == "GET": #如果是get请求
            page = request.GET.get("page") #尝试获取page
            if not page: #默认page 为1
                page = 1
            else:
                page = int(page) #get过来的page参数是字符串
    
            select_page = 3 #每次3页
            page_num = 3 #每页3条
            select_num = select_page*page_num #单次查询9条
            resutl_dict = {}
    
            query_num = page/page_num #获取查询序列号
            if query_num == int(query_num): #如果整除
                query_num = int(query_num)  #返回整形数
            else: #否则
                query_num = int(query_num)+1 #返回整形数加1
    
            start = (query_num - 1)*select_num
            end = query_num*select_num
            articels = Article.objects.all()[start:end] #现在当前查询不会执行,只到调用,当前写法的查询效率和数据库limit语句相似
            #进行分页
            paginator = Paginator(articels,page_num) #分页值分了9条数据
    	page = paginator(page)
    
    1. 如果查询1,2,3,我们请求的时候page是1,2,3

    那如果page = 4 查询的 1

    query_num = 2
    
    start = (query_num-1)*select_num = (2-1)*3 = 3
    
    4 – 3 = 1

    Django个人博客开发之分页与Vue分页_第9张图片

    pageData = paginator(page-start)

    分页视图完整代码    

    \OurBlog\Article\views.py

    def vuePageData_1(request):
        """
            这个函数是用来返回分页数据的,一定要认真
            query_page 分页量
            首先划定逻辑
            每页3条
            每次3页
            到第3页我们返回下5页
            """
        select_page = 3  # 每次3页
        page_num = 3  # 每页3条
        select_num = select_page * page_num  # 单次查询的总条数
        page_result = {}  # 返回的结果
    
        if request.method == "GET":  # 如果是get请求
            page = request.GET.get("page")  # 获取page值,在这里注意一定要用get,如果用[]容易导致如果page没有参数会报错
            if page and int(page) > 1:  # page存在,且大于1
                page = int(page)
            else:  # 设置默认为1
                page = 1
    
            query_num = page / page_num
            if query_num == int(query_num):
                query_num = int(query_num)
            else:
                query_num = int(query_num) + 1
    
            start = (query_num - 1) * select_num
            end = query_num * select_num + 3
            articles = Article.objects.all()[start:end]
            paginator = Paginator(articles, page_num)  # 进行每页5条的分页
            print(page)
            print(start)
    
            pageData = paginator.page(page-start/page_num) #注意加入页面为4 我们的start是9
    
            page_data = []  # 对数据进行从新整合
    
            for data in pageData:
                page_data.append(
                    {
                        "title": data.title,
                        "author": data.author.name,
                        "time": data.time,
                        "picture": data.picture.name,  # 这里要注意,data.picture 返回的是图片对象,我们获取他的name
                        'description': data.description,
                        'id': data.id,
                    }
                )
            page_result["pageData"] = page_data
    
            if page % select_page == 0 and len(paginator.page_range) > 3:
                page_result["page_range"] = [page + page_num * (query_num - 1) for page in paginator.page_range]
            else:
                page_result["page_range"] = [page + page_num * (query_num - 1) for page in paginator.page_range][:-1]
    
            return JsonResponse(page_result)
    

    HTML前端

    \OurBlog\template\myArticle_v1.html

    
    
    
    
    个人博客模板古典系列之――江南墨卷
    
    
    
    
    
    
    
    
    
    
    
    
    

    您现在的位置是:网站首页>>个人日记个人日记

    {% verbatim myblock %}
  • {% endverbatim myblock %}

     

     

     

     

    你可能感兴趣的:(项目开发)