django之ajax

Ajax初识

""" 异步提交 局部刷新
例子:github注册 动态获取用户名实时的跟后端确认并实时展现的前端(局部刷新) 朝发送请求的方式 1.浏览器地址栏直接输入url回车 GET请求 2.a标签href属性 GET请求 3.form表单 GET请求/POST请求 4.ajax GET请求/POST请求 AJAX 不是新的编程语言,而是一种使用现有标准的新方法(比较装饰器) AJAX 最大的优势是在不从新加载整个页面的状况下,能够与服务器交换数据并更新部分网页内容。(这一特色给用户的感觉是在不知不觉中完成请求和响应过程) Ajax咱们只学习jQuery封装以后的版本(不学原生的 原生的复杂而且在实际项目中也通常不用) 因此咱们在前端页面使用ajax的时候须要确保导入了jQuery ps:并不仅有jQuery可以实现ajax,其余的框架也能够 可是换汤不换药 原理是同样的
咱们学的是jQuery版本的ajax,必需要确保html页面已经提早加载了jQuery
"""

Ajax准备知识:JSON

什么是json?

  • JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation)
  • JSON 是轻量级的文本数据交换格式
  • JSON 独立于语言 *
  • JSON 具备自我描述性,更易理解

* JSON 使用 JavaScript 语法来描述数据对象,可是 JSON 仍然独立于语言和平台。JSON 解析器和 JSON 库支持许多不一样的编程语言。css

 啥都别多说了,上图吧!html

 合格的json对象(json只认双引的字符串格式):前端

["one", "two", "three"]
{ "one": 1, "two": 2, "three": 3 }
{"names": ["张三", "李四"] }
[ { "name": "张三"}, {"name": "李四"} ] 

stringify与parse方法

JavaScript中关于JSON对象和字符串转换的两个方法:python

JSON.parse(): 用于将一个 JSON 字符串转换为 JavaScript 对象(json只认双引的字符串格式)jquery

JSON.parse('{"name":"Howker"}');

JSON.stringify(): 用于将 JavaScript 值转换为 JSON 字符串。git

JSON.stringify({"name":"Tonny"})

Ajax简介

AJAXAsynchronous Javascript And XML)翻译成中文就是异步的JavascriptXML”。即便用Javascript语言与服务器进行异步交互,传输的数据为XML(固然,传输的数据不仅是XML)。github

AJAX 不是新的编程语言,而是一种使用现有标准的新方法。ajax

AJAX 最大的优势是在不从新加载整个页面的状况下,能够与服务器交换数据并更新部分网页内容。(这一特色给用户的感觉是在不知不觉中完成请求和响应过程)sql

AJAX 不须要任何浏览器插件,但须要用户容许JavaScript在浏览器上执行。数据库

  • 同步交互:客户端发出一个请求后,须要等待服务器响应结束后,才能发出第二个请求;
  • 异步交互:客户端发出一个请求后,无需等待服务器响应结束,就能够发出第二个请求。

基本语法:

$.ajax({
    url:'',  # 朝后端哪一个地址发送 跟action三种书写方式一致
    type:'get/post',  # 提交方式 默认get 跟form表单method参数一致
    data:{'username':'jason','password':123},  # 要发送的数据
    success:function(args){
      # 异步回调处理机制
    } 
  })

"""
  当你在利用ajax进行先后端交互的时候
  后端不管返回什么都只会被回调函数接受 而再也不影响这个浏览器页面了
"""

 # 扩展 参数  代码发布项目还会涉及
  dataType:'json'
  """
  当后端是以HttpResponse返回的json格式的数据
  默认是不会自动反序列化的
      1.本身手动JSON.parse()
      2.配置dataType参数
  """

补充写法

<script>
       $("#id_submit").click(function () {
        // 朝后端发送ajax请求
        $.ajax({
            // 一、指定朝哪一个后端发ajax请求
            url:"",  // 不写就是朝当前地址提交
            // 二、请求方式
            type:"post",   //不指定默认就是get,都是小写,用ajax提交post数据,后端也是在request.POST中接收
            dataType:"json",
            data:{
                "username":$("#name").val(),
                "password":$("#password").val()
            },
            // 四、回调函数:当后端给你返回结果的时候会自动触发 args接收后端的返回结果
            success:function (args) {
                console.log(args)     // 经过DOM操做动态渲染到第三个input里面
            }
        })
        .done(function(resp) {     // 请求成功之后的操做
                console.log(resp);
            })
        .fail(function(error) {    // 请求失败之后的操做
            console.log(error);
        })
    })
    </script>

结论:

# 结论:写ajax的时候 你能够直接将dataType参数加上 以防万一 或者后端就用JsonResonse
  $.ajax({
    url:'',  # 朝后端哪一个地址发送 跟action三种书写方式一致
    type:'get/post',  # 提交方式 默认get 跟form表单method参数一致
    dataType:'JSON',  
    data:{'username':'jason','password':123},  # 要发送的数据
    success:function(args){
      # 异步回调处理机制
    } 
  })

小案例:

在不刷新的状况下显示计算结果到页面上,页面输入两个整数,经过AJAX传输到后端计算出结果并返回。(也不能在前端计算)

urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    # ajax
    url(r'^ab_ajax/', views.ab_ajax),
]
urls.py

views.py

from django.shortcuts import render,HttpResponse,redirect

# Create your views here.
def ab_ajax(request):   # 和ajax交互的时候,不管返回什么,都不会做用于浏览器,而是交给ajax的回调函数
    if request.method == "POST":
        # print(request.POST)      # <QueryDict: {'i1':['123'],'i2':['345']}>
        i1 = request.POST.get("i1")
        i2 = request.POST.get("i2")
        i3 = int(i1) + int(i2)
        return HttpResponse(i3)
    return render(request,"index.html")
views.py

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!-- Bootstrap3 核心 CSS 文件 -->
    <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <!-- jQuery文件。务必在bootstrap.min.js 以前引入 -->
    <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
    <!-- Bootstrap3 核心 JavaScript 文件 -->
    <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <!-- font-awesome.min.css图标库4.7版本 -->
    <link href="https://cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
</head>
<body>
<input type="text" id="d1"> +
<input type="text" id="d2"> =
<input type="text" id="d3">
<p>
    <button id="btn">点我</button>
</p>
<script>
    // 先给按钮绑定一个点击事件
    $("#btn").click(function () {
        // 朝后端发送ajax请求
        $.ajax({
            // 一、指定朝哪一个后端发ajax请求
            url:"",  // 不写就是朝当前地址提交
            // 二、请求方式
            type:"post",   //不指定默认就是get,都是小写,用ajax提交post数据,后端也是在request.POST中接收
            // 三、数据
            data:{"i1":$("#d1").val(),"i2":$("#d2").val()},
            // 四、回调函数:当后端给你返回结果的时候会自动触发 args接收后端的返回结果
            success:function (args) {
                $("#d3").val(args)     // 经过DOM操做动态渲染到第三个input里面
            }
        })
    })
</script>
</body>
</html>
index.html

补充:若是视图函数返回字典须要序列化

# 针对后端若是是用HttpResponse返回的数据(json模块序列化后) 回调函数不会自动帮你反序列化
# 若是后端直接用的是JsonResponse返回的数据 回调函数会自动帮你反序列化

# HttpResponse解决方式
    1.本身在前端利用JSON.parse(args),手动反序列化
    2.在ajax里面配置一个参数
       dataType:"json",

示例1:后端使用JsonResponse返回数据

urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    # ajax
    url(r'^ab_ajax/', views.ab_ajax),
]
urls.py

views.py

from django.shortcuts import render,HttpResponse,redirect
from django.http import JsonResponse

# Create your views here.
def ab_ajax(request):   # 和ajax交互的时候,不管返回什么,都不会做用于浏览器,而是交给ajax的回调函数
    if request.method == "POST":
        # print(request.POST)
        i1 = request.POST.get("i1")
        i2 = request.POST.get("i2")
        i3 = int(i1) + int(i2)
        d = {"code":100,"msg":i3}
        return JsonResponse(d)
    return render(request,"index.html")
views.py

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!-- Bootstrap3 核心 CSS 文件 -->
    <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <!-- jQuery文件。务必在bootstrap.min.js 以前引入 -->
    <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
    <!-- Bootstrap3 核心 JavaScript 文件 -->
    <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <!-- font-awesome.min.css图标库4.7版本 -->
    <link href="https://cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
</head>
<body>
<input type="text" id="d1"> +
<input type="text" id="d2"> =
<input type="text" id="d3">
<p>
    <button id="btn">点我</button>
</p>
<script>
    // 先给按钮绑定一个点击事件
    $("#btn").click(function () {
        // 朝后端发送ajax请求
        $.ajax({
            // 一、指定朝哪一个后端发ajax请求
            url:"",  // 不写就是朝当前地址提交
            // 二、请求方式
            type:"post",   //不指定默认就是get,都是小写,用ajax提交post数据,后端也是在request.POST中接收
            // 三、数据
            data:{"i1":$("#d1").val(),"i2":$("#d2").val()},
            // 四、回调函数:当后端给你返回结果的时候会自动触发 args接收后端的返回结果
            success:function (args) {
                {#$("#d3").val(args)     // 经过DOM操做动态渲染到第三个input里面#}
                console.log(typeof args)   // 接收到的是对象类型
            }
        })
    })
</script>
</body>
</html>
index.html

示例2:后端用HttpResponse返回的数据(json序列化后的数据)

urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    # ajax
    url(r'^ab_ajax/', views.ab_ajax),
]
urls.py

views.py

from django.shortcuts import render,HttpResponse,redirect
import json
# Create your views here.
def ab_ajax(request):   # 和ajax交互的时候,不管返回什么,都不会做用于浏览器,而是交给ajax的回调函数
    if request.method == "POST":
        # print(request.POST)
        i1 = request.POST.get("i1")
        i2 = request.POST.get("i2")
        i3 = int(i1) + int(i2)
        d = {"code":100,"msg":i3}
        return HttpResponse(json.dumps(d))
    return render(request,"index.html")
views.py

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!-- Bootstrap3 核心 CSS 文件 -->
    <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <!-- jQuery文件。务必在bootstrap.min.js 以前引入 -->
    <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
    <!-- Bootstrap3 核心 JavaScript 文件 -->
    <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <!-- font-awesome.min.css图标库4.7版本 -->
    <link href="https://cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
</head>
<body>
<input type="text" id="d1"> +
<input type="text" id="d2"> =
<input type="text" id="d3">
<p>
    <button id="btn">点我</button>
</p>
<script>
    // 先给按钮绑定一个点击事件
    $("#btn").click(function () {
        // 朝后端发送ajax请求
        $.ajax({
            // 一、指定朝哪一个后端发ajax请求
            url:"",  // 不写就是朝当前地址提交
            // 二、请求方式
            type:"post",   //不指定默认就是get,都是小写,用ajax提交post数据,后端也是在request.POST中接收
            // 三、数据
            data:{"i1":$("#d1").val(),"i2":$("#d2").val()},
            // 四、回调函数:当后端给你返回结果的时候会自动触发 args接收后端的返回结果
            dataType:"json",
            success:function (args) {
                {#$("#d3").val(args)     // 经过DOM操做动态渲染到第三个input里面#}
                console.log(typeof args)   // 接收到的是对象类型
            }
        })
    })
</script>
</body>
</html>
index.html

朝后端传输数据的编码格式(contentType)

# 咱们主要研究post请求数据的编码格式
"""
get请求数据就是直接放在url后面的
url?username=jason&password=123
"""

能够朝后端发送post请求的方式

# 1.form表单
# 2.ajax请求

form表单朝后端发送post请求的编码格式

朝后端传输数据的编码格式

# 1.urlencoded
    
# 2.formdata
    
# 3.json

知识点:

# 默认的数据编码格式是urlencoded
  数据格式:username=jason&password=123
  django后端针对符合urlencoded编码格式的数据都会自动帮你解析封装到request.POST中
      username=jason&password=123    >>> request.POST
  
# 若是你把编码格式改为formdata,那么针对普通的键值对仍是解析到request.POST中而将文件解析到request.FILES中
  
  form表单是没有办法发送json格式数据的

查看数据编码格式:

查看数据格式:

 

 ajax朝后端发送post请求的编码格式

知识点:

# 默认的编码格式也是urlencoded
  数据格式:username=jason&age=20
    django后端针对符合urlencoded编码格式的数据都会自动帮你解析封装到request.POST中
      username=jason&age=20    >>> request.POST

ajax发送json格式数据

# 宗旨:
  先后端传输数据的时候必定要确保编码格式跟数据真正的格式是一致的
  不要骗人家!!!
# ajax朝后端发送的json数据:(注意要先将data数据序列化成json格式字符串)
    格式:{"username":"jason","age":25}  
    后端在request.POST里面确定找不到
    由于django针对json格式的数据 不会作任何的处理,会存放在request.body中(二进制形式)b'{"username":"jason","age":25}'

# request对象方法补充
    request.is_ajax()
        判断当前请求是不是ajax请求 返回布尔值

正确示例:

urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    # ajax发送json格式数据
    url(r'^ab_json/', views.ab_json),
]
urls.py

views.py

from django.shortcuts import render

# Create your views here.
def ab_json(request):
    import json
    if request.is_ajax():   # 判断当前请求是不是ajax请求 返回布尔值
# 针对json格式数据须要手动处理,django不会作任何处理,存放在request.body
json_bytes = request.body # b'{"username":"jason","age":25}' # 反序列化方式一:先decode解码再loads反序列化 # json_str = json_bytes.decode('utf-8') # json_dict = json.loads(json_str) # 反序列化方式二:json.loads括号内若是传入了一个二进制格式的数据那么内部自动解码再反序列化 json_dict = json.loads(json_bytes) print(json_dict,type(json_dict)) return render(request,"ab_json.html")

ab_json.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!-- Bootstrap3 核心 CSS 文件 -->
    <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <!-- jQuery文件。务必在bootstrap.min.js 以前引入 -->
    <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
    <!-- Bootstrap3 核心 JavaScript 文件 -->
    <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <!-- font-awesome.min.css图标库4.7版本 -->
    <link href="https://cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
</head>
<body>
<button class="btn btn-danger" id="d1">点我</button>

<script>
    $("#d1").click(function () {
        $.ajax({
            url:"",
            type:"post",
            data:JSON.stringify({"username":"jason","age":20}),   // 序列化为json格式字符串
            dataType:'JSON',
contentType:
"application/json", // 编码格式改成json,指定编码格式,默认是urlencoded格式 success:function (args) { } }) }) </script> </body> </html>

总结:

# ajax发送json格式数据须要注意点
    1.contentType参数指定成:application/json
    2.数据是真正的json格式数据
    3.django后端不会帮你处理json格式数据须要你本身去request.body获取并处理

ajax发送文件

"""
ajax发送文件须要借助于js内置对象FormData

"""

示例:

urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    # ajax发送文件
    url(r'^ab_file/', views.ab_file),
]

views.py

from django.shortcuts import render

# Create your views here.
def ab_file(request):
    if request.is_ajax():
        if request.method == 'POST':
            print(request.POST)
            print(request.FILES)
    return render(request,"ab_file.html")

ab_file.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!-- Bootstrap3 核心 CSS 文件 -->
    <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <!-- jQuery文件。务必在bootstrap.min.js 以前引入 -->
    <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
    <!-- Bootstrap3 核心 JavaScript 文件 -->
    <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <!-- font-awesome.min.css图标库4.7版本 -->
    <link href="https://cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
</head>
<body>
    <p>usernmae:<input type="text" id="d1"></p>
    <p>password:<input type="text" id="d2"></p>
    <p><input type="file" id="d3"></p>
    <button class="btn btn-info" id="d4">点我</button>
    <script>
        // 点击按钮朝后端发送普通键值对和文件数据
        $("#d4").on("click",function () {
            // 1.须要先利用FormData内置对象
            let formDateObj = new FormData();
            // 2.添加普通的键值对
            formDateObj.append('username',$('#d1').val());
            formDateObj.append('password',$('#d2').val());
            // 3.添加文件对象,$('#d3')[0]先将jQuery对象转换为DOM对象
            formDateObj.append('myfile',$('#d3')[0].files[0])
            // 4.将对象基于ajax发送给后端
            $.ajax({
                url:'',
                type:'post',
                data:formDateObj,  // 直接将对象放在data后面便可
                dataType:'JSON',
                // ajax发送文件必需要指定的两个参数
                contentType:false,  // 不需使用任何编码 django后端可以自动识别formdata对象
                processData:false,  // 告诉你的浏览器不要对你的数据进行任何处理

                success:function (args) {

                }
            })
        })

    </script>
</body>
</html>

总结:

# 总结:
    1.须要利用内置对象FormData
                // 2 添加普通的键值对
        formDateObj.append('username',$('#d1').val());
        formDateObj.append('password',$('#d2').val());
        // 3 添加文件对象
        formDateObj.append('myfile',$('#d3')[0].files[0])
    2.须要指定两个关键性的参数
                contentType:false,  // 不需使用任何编码 django后端可以自动识别formdata对象
        processData:false,  // 告诉你的浏览器不要对你的数据进行任何处理
    3.django后端可以直接识别到formdata对象而且可以将内部的普通键值自动解析并封装到request.POST中 文件数据自动解析并封装到request.FILES中

django自带的序列化组件(drf作铺垫)

"""
若是发现你能够直接使用MySQL可是没法使用sqlite3
不要慌张不要恐惧 你只须要按照以前MySQL的操做将sqlite3的驱动装一下便可
"""
# 需求:在前端给我获取到后端用户表里面全部的数据 而且要是列表套字典

示例:

urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    # 序列化组件相关
    url(r'^ab_ser/', views.ab_ser),
]

views.py

from django.shortcuts import render,HttpResponse
from app01 import models
from django.http import JsonResponse
from django.core import serializers     # 序列化组件serializers

# Create your views here.
def ab_ser(request):
    user_queryset = models.User.objects.all()
    # 需求返回[{},{},{},{},{}]格式
    # 方法一:手动实现
    # user_list = []
    # for user_obj in user_queryset:
    #     tmp = {
    #         'pk':user_obj.pk,
    #         'username':user_obj.username,
    #         'age':user_obj.age,
    #         'gender':user_obj.get_gender_display(),
    #     }
    #     user_list.append(tmp)
    #
    # return JsonResponse(user_list,safe=False)

    # 方法二:序列化
    res = serializers.serialize('json',user_queryset)     # 第一个参数:序列化成什么格式,第二个参数:要序列化的数据
    return HttpResponse(res)
"""
先后端分离的项目
    做为后端开发的你只须要写代码将数据处理好
    可以序列化返回给前端便可 
        再写一个接口文档 告诉前端每一个字段表明的意思便可
# 手动实现
[
  {
    "pk": 1,
    "username": "jason",
    "age": 20,
    "gender": "male"
  },
  {
    "pk": 2,
    "username": "egon",
    "age": 22,
    "gender": "female"
  },
  {
    "pk": 3,
    "username": "tank",
    "age": 25,
    "gender": "male"
  },
  {
    "pk": 4,
    "username": "lxx",
    "age": 30,
    "gender": "other"
  }
]

使用serializers序列化
[
  {
    "model": "app01.user",
    "pk": 1,
    "fields": {
      "username": "jason",
      "age": 20,
      "gender": 1
    }
  },
  {
    "model": "app01.user",
    "pk": 2,
    "fields": {
      "username": "egon",
      "age": 22,
      "gender": 2
    }
  },
  {
    "model": "app01.user",
    "pk": 3,
    "fields": {
      "username": "tank",
      "age": 25,
      "gender": 1
    }
  },
  {
    "model": "app01.user",
    "pk": 4,
    "fields": {
      "username": "lxx",
      "age": 30,
      "gender": 3
    }
  }
]
写接口就是利用序列化组件渲染数据而后写一个接口文档 该交代交代一下就完事了
"""

ajax结合sweetalert实现删除按钮的二次确认

"""
本身要学会如何拷贝
学会基于别人的基础之上作修改
研究各个参数表示的意思 而后找葫芦画瓢
"""

 示例:

urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    # 用户展现页
    url(r'^user/list/', views.user_list),
    # 删除用户
    url(r'^delete/user/',views.delete_user),
]

views.py

from django.shortcuts import render,HttpResponse
from django.http import JsonResponse
from app01 import models
import time

# Create your views here.
def user_list(request):

    user_queryset = models.User.objects.all()
    return render(request,"user_list.html",locals())

def delete_user(request):
    """
    先后端在用ajax进行交互的时候 后端一般给ajax的回调函数返回一个字典格式的数据
    """
    if request.is_ajax():
        if request.method == 'POST':
            back_dic = {"code":1000,'msg':''}
            time.sleep(3)  # 模拟操做数据的延迟
            delete_id = request.POST.get('delete_id')
            models.User.objects.filter(pk=delete_id).delete()
            back_dic['msg'] = '数据已经删了,你赶忙跑路!'
            # 咱们须要告诉前端咱们操做的结果
            return JsonResponse(back_dic)

user_list.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    {% load static %}
    <!-- Bootstrap3 核心 CSS 文件 -->
    <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <!-- jQuery文件。务必在bootstrap.min.js 以前引入 -->
    <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
    <!-- Bootstrap3 核心 JavaScript 文件 -->
    <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <!-- font-awesome.min.css图标库4.7版本 -->
    <link href="https://cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
    <link rel="stylesheet" href="{% static "bootstrap-sweetalert-master/dist/sweetalert.css" %}">
    <script src="{% static "bootstrap-sweetalert-master/dist/sweetalert.min.js" %}"></script>
</head>
<body>
    <h1 class="text-center">数据展现</h1>
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <table class="table-striped table table-hover">
                <thead>
                    <tr>
                        <th>ID</th>
                        <th>username</th>
                        <th>age</th>
                        <th>gender</th>
                        <th>actions</th>
                    </tr>
                </thead>
                <tbody>
                    {% for user_obj in user_queryset %}
                        <tr>
                            <td>{{ user_obj.pk }}</td>
                            <td>{{ user_obj.username }}</td>
                            <td>{{ user_obj.age }}</td>
                            <td>{{ user_obj.get_gender_display }}</td>
                            <td>
                                <button class="btn btn-primary btn-xs">编辑</button>
                                <button class="btn btn-danger btn-xs del" delete_id="{{ user_obj.pk }}">删除</button>
                            </td>
                        </tr>
                    {% endfor %}

                </tbody>
            </table>
        </div>
    </div>
</div>

<script>
        $('.del').on('click',function () {
        // 先将当前标签对象存储起来
        let currentBtn = $(this);       // this指代当前被操做对象自己
        // 二次确认弹框
        swal({
          title: "你肯定要删吗?",
          text: "删除可就找不回来了哦!",
          type: "warning",
          showCancelButton: true,    // 是否显示取消按钮
          confirmButtonClass: "btn-danger",      // 确认按钮的样式类
          confirmButtonText: "删除",   // 确认按钮文本
          cancelButtonText: "取消",         // 取消按钮文本
          closeOnConfirm: false,
          closeOnCancel: false,
          showLoaderOnConfirm: true      // 显示正在删除的动画效果   // 等待后端处理时间 。。。动画
        },
        function(isConfirm) {    // isConfirm 是用来判断用户是否点了确认
          if (isConfirm) {
                // 朝后端发送ajax请求删除数据以后 再弹下面的提示框
                $.ajax({
                    {#url:'/delete/user/' + currentBtn.attr('delete_id'),  // 1 传递主键值方式1#}
                    url:'/delete/user/',  // 2 方式2,放在data里面
                    type:'post',
                    data:{'delete_id':currentBtn.attr('delete_id')},
                    success:function (args) {  // args = {'code':'','msg':''}
                        // 判断响应状态码 而后作不一样的处理
                        if(args.code === 1000){
                            swal("删了!", args.msg, "success");
                            // 1.lowb版本 直接刷新当前页面
                            {#window.location.reload()#}
                            // 2.利用DOM操做 动态刷新 经过当前被操做对象,移动到数据那一行对应的标签,删除行标签
                            currentBtn.parent().parent().remove()
                        }else{
                            swal('完了','出现了未知的错误','info')
                        }
                    }

                })

          } else {
            swal("怂逼", "不要说我认识你", "error");
          }
        });
    })
</script>
</body>
</html>

注意:上面代码在删除时有个bug,中文汉字被覆盖

 解决方法:

一、先找到被遮挡文字的标签位置

 二、在user_list.html页面中添加内部css样式表,为找到的标签添加一个上填充padding

<style>
        div.sweet-alert h2 {
            padding-top: 10px;
        }
</style>

 

不使用sweetAlert的思路

res = confirm()
    if(res){
      $.ajax({})
    }else{
      不发
    }

 批量插入

需求:

# 访问url的时候
# 先Book表插入1000条数据
# 再将说有的数据查询并展现到前端页面

low版方法:使用for循环一条条插入,插入1000条

urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    # 批量插入
    url(r'^ab_batch',views.ab_batch),
]
urls.py

views.py

from django.shortcuts import render,HttpResponse
from django.http import JsonResponse
from app01 import models

# Create your views here.
def ab_batch(request):
    # 先Book表插入1000条数据
    for i in range(1000):
        models.Book.objects.create(title="第%s本书" %i)
    # 再将说有的数据查询并展现到前端页面
    book_queryset = models.Book.objects.all()

    return render(request,"ab_batch.html",locals())
views.py

ab_batch.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!-- Bootstrap3 核心 CSS 文件 -->
    <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <!-- jQuery文件。务必在bootstrap.min.js 以前引入 -->
    <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
    <!-- Bootstrap3 核心 JavaScript 文件 -->
    <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <!-- font-awesome.min.css图标库4.7版本 -->
    <link href="https://cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
</head>
<body>
    {% for book_obj in book_queryset %}
        <p>{{ book_obj.title }}</p>
    {% endfor %}

</body>
</html>
ab_batch.html

批量插入:bulk_create(),能够发现速度明显加快,插入10000条并且比上面low版速度还快

urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    # 批量插入
    url(r'^ab_batch',views.ab_batch),
]
urls.py

views.py

from django.shortcuts import render,HttpResponse
from django.http import JsonResponse
from app01 import models

# Create your views here.
def ab_batch(request):

    book_list = []
    for i in range(10000):
        book_obj = models.Book(title="第%s本书" %i)
        book_list.append(book_obj)
        # 上面两行能够直接缩写成一行
        # book_list.append(models.Book(title="第%s本书" %i))

    # 一次性插入
    models.Book.objects.bulk_create(book_list)
    # 再将说有的数据查询并展现到前端页面
    book_queryset = models.Book.objects.all()

    return render(request,"ab_batch.html",locals())
views.py

ab_batch.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!-- Bootstrap3 核心 CSS 文件 -->
    <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <!-- jQuery文件。务必在bootstrap.min.js 以前引入 -->
    <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
    <!-- Bootstrap3 核心 JavaScript 文件 -->
    <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <!-- font-awesome.min.css图标库4.7版本 -->
    <link href="https://cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
</head>
<body>
    {% for book_obj in book_queryset %}
        <p>{{ book_obj.title }}</p>
    {% endfor %}

</body>
</html>
ab_batch.html

总结:

# 当你想要批量插入数据的时候 使用orm给你提供的bulk_create可以大大的减小操做时间

分页器推导

"""
总数据100 每页展现10 须要10
总数据101 每页展现10 须要11
总数据99 每页展现10  须要10

如何经过代码动态的计算出到底须要多少页?

在制做页码个数的时候 通常状况下都是奇数个        符合对称美的标准
"""

初步推导:

urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    # 分页
    url(r'^ab_batch',views.ab_batch),
]

views.py

from django.shortcuts import render,HttpResponse
from django.http import JsonResponse
from app01 import models

def ab_batch(request):
    # 分页器推导
    book_list = models.Book.objects.all()
    # 想访问哪一页
    current_page = request.GET.get('page', 1)  # 若是获取不到当前页码 就展现第一页
    # 数据类型转换
    try:
        current_page = int(current_page)
    except Exception:
        current_page = 1

    # 每页展现多少条
    per_page_num = 10
    # 起始位置
    start_page = (current_page - 1) * per_page_num
    # 终止位置
    end_page = current_page * per_page_num

    # 计算出到底须要多少页
    all_count = book_list.count()

    page_count, more = divmod(all_count, per_page_num)
    if more:
        page_count += 1

    if current_page <= 1:
        prev_page = '<li class="disabled"><a href="#">上一页</a></li>'
    else:
        prev_page = '<li><a href="?page=%s">上一页</a></li>' % (current_page - 1,)
    page_html = ''
    current_page_new = current_page
    if current_page < 6:
        current_page = 6
    for i in range(current_page - 5, current_page + 6):
        if current_page_new == i:
            page_html += '<li class="active"><a href="?page=%s">%s</a></li>' % (i, i)
        else:
            page_html += '<li><a href="?page=%s">%s</a></li>' % (i, i)

    if current_page >= page_count:
        next_page = '<li class="disabled"><a href="#">下一页</a></li>'
    else:
        next_page = '<li><a href="?page=%s">下一页</a></li>' % (current_page + 1,)


    book_queryset = book_list[start_page:end_page]

    return render(request,"ab_batch.html",locals())
'''
per_page_num = 10
current_page                start_page                  end_page
    1                           0                           10
    2                           10                          20
    3                           20                          30
    4                           30                          40

per_page_num = 5
current_page                start_page                  end_page
    1                           0                           5
    2                           5                           10
    3                           15                          20
    4                           25                          30
    
规律:
start_page = (current_page - 1) * per_page_num
end_page = current_page * per_page_num
'''

ab_batch.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!-- Bootstrap3 核心 CSS 文件 -->
    <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <!-- jQuery文件。务必在bootstrap.min.js 以前引入 -->
    <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
    <!-- Bootstrap3 核心 JavaScript 文件 -->
    <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <!-- font-awesome.min.css图标库4.7版本 -->
    <link href="https://cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
</head>
<body>
{% for book_obj in book_queryset %}
    <p>{{ book_obj.title }}</p>
{% endfor %}

<div class="text-center">
    <nav aria-label="Page navigation">
    <ul class="pagination ">
    <li><a href="?page=1">首页</a></li>
    {{ prev_page|safe }}
    {{ page_html|safe }}
    {{ next_page|safe }}
    <li><a href="?page={{ page_count }}">尾部</a></li>
    </ul>
    </nav>
</div>

</body>
</html>

推导过程

  1.queryset对象是直接切片操做的
  2.用户到底要访问哪一页 如何肯定?        url?page=1
      current_page = request.GET.get('page',1)
    # 获取到的数据都是字符串类型 你须要注意类型转换
  3.本身规定每页展现多少条数据
      per_page_num = 10
  4.切片的起始位置和终止位置
      start_page = (current_page - 1)* per_page_num
    end_page = current_page * per_page_num
    # 利用简单找规律 找出上述四个参数的规律
  5.当前数据的总条数
      book_queryset.count()
  6.如何肯定总共须要多少页才能展现完全部的数据
      # 利用python内置函数divmod()
    page_count, more = divmod(all_count,per_page_num)
    if more:
      page_count += 1
  7.前端模版语法是没有range功能的
      # 前端代码不必定非要在前端书写 也能够在后端生成传递给页面
  8.针对须要展现的页码须要你本身规划好到底展现多少个页码
      # 通常状况下页码的个数设计都是奇数(符合审美标准)  11个页码
    当前页减5
    当前页加6
    你能够给标签价样式从而让选中的页码高亮显示
  9.针对页码小于6的状况 你须要作处理 不能再减

终极版分页器

初级版是自定义分页器开发流程的基本思路,咱们不须要掌握代码的编写,只须要掌握基本用法便可

自定义分页器封装代码

注意:

自定义的分页器是基于bootstrap样式来的 因此须要提早导入bootstrap
bootstrap 版本 v3
jQuery 版本 v3

# 分页器
class Pagination(object):
    def __init__(self, current_page, all_count, per_page_num=2, pager_count=11):
        """
        封装分页相关数据
        :param current_page: 当前页
        :param all_count:    数据库中的数据总条数
        :param per_page_num: 每页显示的数据条数
        :param pager_count:  最多显示的页码个数
        """
        try:
            current_page = int(current_page)
        except Exception as e:
            current_page = 1

        if current_page < 1:
            current_page = 1

        self.current_page = current_page

        self.all_count = all_count
        self.per_page_num = per_page_num

        # 总页码
        all_pager, tmp = divmod(all_count, per_page_num)
        if tmp:
            all_pager += 1
        self.all_pager = all_pager

        self.pager_count = pager_count
        self.pager_count_half = int((pager_count - 1) / 2)

    @property
    def start(self):
        return (self.current_page - 1) * self.per_page_num

    @property
    def end(self):
        return self.current_page * self.per_page_num

    def page_html(self):
        # 若是总页码 < 11个:
        if self.all_pager <= self.pager_count:
            pager_start = 1
            pager_end = self.all_pager + 1
        # 总页码  > 11
        else:
            # 当前页若是<=页面上最多显示11/2个页码
            if self.current_page <= self.pager_count_half:
                pager_start = 1
                pager_end = self.pager_count + 1

            # 当前页大于5
            else:
                # 页码翻到最后
                if (self.current_page + self.pager_count_half) > self.all_pager:
                    pager_end = self.all_pager + 1
                    pager_start = self.all_pager - self.pager_count + 1
                else:
                    pager_start = self.current_page - self.pager_count_half
                    pager_end = self.current_page + self.pager_count_half + 1

        page_html_list = []
        # 添加前面的nav和ul标签
        page_html_list.append('''
                  <nav aria-label='Page navigation>'
                      <ul class='pagination'>
                            ''')
        first_page = '<li><a href="?page=%s">首页</a></li>' % (1)
        page_html_list.append(first_page)

        if self.current_page <= 1:
            prev_page = '<li class="disabled"><a href="#">上一页</a></li>'
        else:
            prev_page = '<li><a href="?page=%s">上一页</a></li>' % (self.current_page - 1,)

        page_html_list.append(prev_page)

        for i in range(pager_start, pager_end):
            if i == self.current_page:
                temp = '<li class="active"><a href="?page=%s">%s</a></li>' % (i, i,)
            else:
                temp = '<li><a href="?page=%s">%s</a></li>' % (i, i,)
            page_html_list.append(temp)

        if self.current_page >= self.all_pager:
            next_page = '<li class="disabled"><a href="#">下一页</a></li>'
        else:
            next_page = '<li><a href="?page=%s">下一页</a></li>' % (self.current_page + 1,)
        page_html_list.append(next_page)

        last_page = '<li><a href="?page=%s">尾页</a></li>' % (self.all_pager,)
        page_html_list.append(last_page)
        # 尾部添加标签
        page_html_list.append('''
                      </ul>
                   </nav>
                ''')
        return ''.join(page_html_list)

自定义分页器拷贝及使用

"""
当咱们须要使用到非django内置的第三方功能或者组件代码的时候
咱们通常状况下会在项目根目录建立一个名为utils文件夹 在该文件夹内对模块进行功能性划分
    utils也能够能够在每一个应用下建立 具体结合实际状况

咱们到了后期封装代码的时候 再也不局限于函数
仍是尽可能朝面向对象去封装

咱们自定义的分页器是基于bootstrap样式来的 因此你须要提早导入bootstrap
    bootstrap 版本 v3
    jQuery        版本 v3
"""

一、在django项目根目录或app01应用目录新建一个utils文件夹用于存放第三方功能或模块

urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    # 分页
    url(r'^ab_batch',views.ab_batch),
]

mypage.py

# 分页器
class Pagination(object):
    def __init__(self, current_page, all_count, per_page_num=2, pager_count=11):
        """
        封装分页相关数据
        :param current_page: 当前页
        :param all_count:    数据库中的数据总条数
        :param per_page_num: 每页显示的数据条数
        :param pager_count:  最多显示的页码个数
        """
        try:
            current_page = int(current_page)
        except Exception as e:
            current_page = 1

        if current_page < 1:
            current_page = 1

        self.current_page = current_page

        self.all_count = all_count
        self.per_page_num = per_page_num

        # 总页码
        all_pager, tmp = divmod(all_count, per_page_num)
        if tmp:
            all_pager += 1
        self.all_pager = all_pager

        self.pager_count = pager_count
        self.pager_count_half = int((pager_count - 1) / 2)

    @property
    def start(self):
        return (self.current_page - 1) * self.per_page_num

    @property
    def end(self):
        return self.current_page * self.per_page_num

    def page_html(self):
        # 若是总页码 < 11个:
        if self.all_pager <= self.pager_count:
            pager_start = 1
            pager_end = self.all_pager + 1
        # 总页码  > 11
        else:
            # 当前页若是<=页面上最多显示11/2个页码
            if self.current_page <= self.pager_count_half:
                pager_start = 1
                pager_end = self.pager_count + 1

            # 当前页大于5
            else:
                # 页码翻到最后
                if (self.current_page + self.pager_count_half) > self.all_pager:
                    pager_end = self.all_pager + 1
                    pager_start = self.all_pager - self.pager_count + 1
                else:
                    pager_start = self.current_page - self.pager_count_half
                    pager_end = self.current_page + self.pager_count_half + 1

        page_html_list = []
        # 添加前面的nav和ul标签
        page_html_list.append('''
                  <nav aria-label='Page navigation>'
                      <ul class='pagination'>
                            ''')
        first_page = '<li><a href="?page=%s">首页</a></li>' % (1)
        page_html_list.append(first_page)

        if self.current_page <= 1:
            prev_page = '<li class="disabled"><a href="#">上一页</a></li>'
        else:
            prev_page = '<li><a href="?page=%s">上一页</a></li>' % (self.current_page - 1,)

        page_html_list.append(prev_page)

        for i in range(pager_start, pager_end):
            if i == self.current_page:
                temp = '<li class="active"><a href="?page=%s">%s</a></li>' % (i, i,)
            else:
                temp = '<li><a href="?page=%s">%s</a></li>' % (i, i,)
            page_html_list.append(temp)

        if self.current_page >= self.all_pager:
            next_page = '<li class="disabled"><a href="#">下一页</a></li>'
        else:
            next_page = '<li><a href="?page=%s">下一页</a></li>' % (self.current_page + 1,)
        page_html_list.append(next_page)

        last_page = '<li><a href="?page=%s">尾页</a></li>' % (self.all_pager,)
        page_html_list.append(last_page)
        # 尾部添加标签
        page_html_list.append('''
                      </ul>
                   </nav>
                ''')
        return ''.join(page_html_list)
mypage.py

views.py后端使用

from django.shortcuts import render,HttpResponse
from django.http import JsonResponse
from app01 import models
from utils.mypage import Pagination    # 导入分页器,这里utils文件夹在根目录下,若是在app01应用目录下使用from app01.utils.mypage import Pagination

def ab_batch(request):
    # 分页器推导
    book_list = models.Book.objects.all()
    # 想访问哪一页
    current_page = request.GET.get('page', 1)  # 若是获取不到当前页码 就展现第一页

    # 计算出到底须要多少页
    all_count = book_list.count()

    page_obj = Pagination(current_page=current_page, all_count=all_count, per_page_num=10)
    page_queryset = book_list[page_obj.start:page_obj.end]
    return render(request, 'ab_batch.html', locals())

前端

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!-- Bootstrap3 核心 CSS 文件 -->
    <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <!-- jQuery文件。务必在bootstrap.min.js 以前引入 -->
    <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
    <!-- Bootstrap3 核心 JavaScript 文件 -->
    <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <!-- font-awesome.min.css图标库4.7版本 -->
    <link href="https://cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
</head>
<body>
{% for book_obj in book_queryset %}
    <p>{{ book_obj.title }}</p>
{% endfor %}

<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            {% for book in page_queryset %}
            <p>{{ book.title }}</p>
            {% endfor %}
<div class="text-center"> {{ page_obj.page_html
|safe }}
</div>
</div> </div> </div> </body> </html>

 Django自带的分页器(paginator)简介

在页面显示分页数据,须要用到Django分页器组件

from django.core.paginator import Paginator

Paginator对象:    paginator = Paginator(user_list, 10)
# per_page: 每页显示条目数量
# count:    数据总个数
# num_pages:总页数
# page_range:总页数的索引范围,如: (1,10),(1,200)
# page:     page对象    
page对象:page=paginator.page(1)
# has_next              是否有下一页
# next_page_number      下一页页码
# has_previous          是否有上一页
# previous_page_number  上一页页码
# object_list           分页以后的数据列表
# number                当前页
# paginator             paginator对象

应用view层

from django.shortcuts import render,HttpResponse

# Create your views here.
from app01.models import *
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger

def index(request):

    '''
    批量导入数据:

    Booklist=[]
    for i in range(100):
        Booklist.append(Book(title="book"+str(i),price=30+i*i))
    Book.objects.bulk_create(Booklist)
    '''

    '''
分页器的使用:

    book_list=Book.objects.all()

    paginator = Paginator(book_list, 10)

    print("count:",paginator.count)           #数据总数
    print("num_pages",paginator.num_pages)    #总页数
    print("page_range",paginator.page_range)  #页码的列表



    page1=paginator.page(1) #第1页的page对象
    for i in page1:         #遍历第1页的全部数据对象
        print(i)

    print(page1.object_list) #第1页的全部数据


    page2=paginator.page(2)

    print(page2.has_next())            #是否有下一页
    print(page2.next_page_number())    #下一页的页码
    print(page2.has_previous())        #是否有上一页
    print(page2.previous_page_number()) #上一页的页码



    # 抛错
    #page=paginator.page(12)   # error:EmptyPage

    #page=paginator.page("z")   # error:PageNotAnInteger

    '''


    book_list=Book.objects.all()

    paginator = Paginator(book_list, 10)
    page = request.GET.get('page',1)
    currentPage=int(page)


    try:
        print(page)
        book_list = paginator.page(page)
    except PageNotAnInteger:
        book_list = paginator.page(1)
    except EmptyPage:
        book_list = paginator.page(paginator.num_pages)


    return render(request,"index.html",{"book_list":book_list,"paginator":paginator,"currentPage":currentPage})

模板层

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" 
    integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>

<div class="container">

    <h4>分页器</h4>
    <ul>

        {% for book in book_list %}
             <li>{{ book.title }} -----{{ book.price }}</li>
        {% endfor %}

     </ul>


    <ul class="pagination" id="pager">

                 {% if book_list.has_previous %}
                    <li class="previous"><a href="/index/?page={{ book_list.previous_page_number }}">上一页</a></li>
                 {% else %}
                    <li class="previous disabled"><a href="#">上一页</a></li>
                 {% endif %}


                 {% for num in paginator.page_range %}

                     {% if num == currentPage %}
                       <li class="item active"><a href="/index/?page={{ num }}">{{ num }}</a></li>
                     {% else %}
                       <li class="item"><a href="/index/?page={{ num }}">{{ num }}</a></li>

                     {% endif %}
                 {% endfor %}



                 {% if book_list.has_next %}
                    <li class="next"><a href="/index/?page={{ book_list.next_page_number }}">下一页</a></li>
                 {% else %}
                    <li class="next disabled"><a href="#">下一页</a></li>
                 {% endif %}

            </ul>
</div>



</body>
</html>

扩展

核心逻辑

    '''
    显示左5,右5,总共11个页,
    1 若是总页码大于11
        1.1 if 当前页码减5小于1,要生成1到12的列表(顾头不顾尾,共11个页码)
            page_range=range(1,12)
        1.2 elif 当前页码+5大于总页码,生成当前页码减10,到当前页码加1的列表(顾头不顾尾,共11个页码)
            page_range=range(paginator.num_pages-10,paginator.num_pages+1)
        1.3 else 生成当前页码-5,到当前页码+6的列表
            page_range=range(current_page_num-5,current_page_num+6)
    2 其它状况,生成的列表就是pageinator的page_range
        page_range=paginator.page_range

    '''

使用案例:

视图层

def page_test(request):
    # book_list=[]
    # for i in range(100):
    #     book=Book(name='book%s'%i,price=10+i,pub_date='2018-09-18',publish_id=1)
    #     book_list.append(book)
    # Book.objects.bulk_create(book_list,10)
    book_list=Book.objects.all()
    # 生成paginator对象,传入书籍列表,每页10条数据
    paginator=Paginator(book_list,3)
    # 总页码数
    print(paginator.num_pages)
    # 页码列表
    print(paginator.page_range)
    # 总数据
    print(paginator.count)
    # 获取页面传来的页码
    current_page=int(request.GET.get('page',1))
    page_range=[]
    # 左5 右5

    # 获取页面传来的页码的page对象
    try:
        page=paginator.page(current_page)
        # print(page.has_next())            #是否有下一页
        # print(page.next_page_number())    #下一页的页码
        # print(page.has_previous())        #是否有上一页
        # print(page.previous_page_number()) #上一页的页码
        # 循环打印出当页对象
        for i in page:
            print(i)
    except Exception as e:
        current_page=1
        page = paginator.page(1)
    if paginator.num_pages>11:
        if current_page+5>paginator.num_pages:
            page_range=range(paginator.num_pages-10,paginator.num_pages+1)
        elif current_page-5<1:
            page_range=range(1,12)
        else:
            page_range=range(current_page-5,current_page+6)
    else:
        page_range=paginator.page_range



    return render(request,'page_test.html',locals())

模板层

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css">
    <title>Title</title>
</head>
<body>

<ul>

    {% for foo in page %}
        <li>{{ foo.name }}</li>

    {% endfor %}

</ul>
<nav aria-label="Page navigation">
    <ul class="pagination">
        {% if page.has_previous %}
            <li>
                <a href="/page_test/?page={{ page.previous_page_number }}" aria-label="Previous">
                    <span aria-hidden="true">上一页</span>
                </a>
            </li>
        {% else %}
            <li class="disabled">
                <a href="#" aria-label="Previous">
                    <span aria-hidden="true">上一页</span>
                </a>
            </li>
        {% endif %}

        {% for foo in page_range %}
            {% if current_page == foo %}
                <li class="active"><a href="/page_test/?page={{ foo }}">{{ foo }}</a></li>
            {% else %}
                <li><a href="/page_test/?page={{ foo }}">{{ foo }}</a></li>
            {% endif %}

        {% endfor %}
        {% if page.has_next %}
            <li>
                <a href="/page_test/?page={{ page.next_page_number }}" aria-label="Next">
                    <span aria-hidden="true">下一页</span>
                </a>
            </li>
        {% else %}
            <li class="disabled">
                <a href="#" aria-label="Next">
                    <span aria-hidden="true">下一页</span>
                </a>
            </li>

        {% endif %}

    </ul>
</nav>


</body>
</html>
相关文章
相关标签/搜索