zoukankan      html  css  js  c++  java
  • 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 库支持许多不同的编程语言。

     啥都别多说了,上图吧!

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

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

    stringify与parse方法

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

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

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

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

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

    Ajax简介

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

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

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

    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({
                // 1、指定朝哪个后端发ajax请求
                url:"",  // 不写就是朝当前地址提交
                // 2、请求方式
                type:"post",   //不指定默认就是get,都是小写,用ajax提交post数据,后端也是在request.POST中接收
                dataType:"json",
                data:{
                    "username":$("#name").val(),
                    "password":$("#password").val()
                },
                // 4、回调函数:当后端给你返回结果的时候会自动触发 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({
                // 1、指定朝哪个后端发ajax请求
                url:"",  // 不写就是朝当前地址提交
                // 2、请求方式
                type:"post",   //不指定默认就是get,都是小写,用ajax提交post数据,后端也是在request.POST中接收
                // 3、数据
                data:{"i1":$("#d1").val(),"i2":$("#d2").val()},
                // 4、回调函数:当后端给你返回结果的时候会自动触发 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({
                // 1、指定朝哪个后端发ajax请求
                url:"",  // 不写就是朝当前地址提交
                // 2、请求方式
                type:"post",   //不指定默认就是get,都是小写,用ajax提交post数据,后端也是在request.POST中接收
                // 3、数据
                data:{"i1":$("#d1").val(),"i2":$("#d2").val()},
                // 4、回调函数:当后端给你返回结果的时候会自动触发 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({
                // 1、指定朝哪个后端发ajax请求
                url:"",  // 不写就是朝当前地址提交
                // 2、请求方式
                type:"post",   //不指定默认就是get,都是小写,用ajax提交post数据,后端也是在request.POST中接收
                // 3、数据
                data:{"i1":$("#d1").val(),"i2":$("#d2").val()},
                // 4、回调函数:当后端给你返回结果的时候会自动触发 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,中文汉字被覆盖

     解决方法:

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

     2、在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
    """

    1、在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>
    
  • 相关阅读:
    js 小数乘积位数太长
    微信浏览器跳转外部浏览器 app下载
    linux 查询制定目录的制定内容
    windows apache 跳转 tomcat 代理
    windows版 nginx配置反向代理实例教程 跳转tomcat和php网站
    概率论公式
    Python scipy 计算短时傅里叶变换(Short-time Fourier transforms)
    Centos 解决SSH 免密码登录 以及Crontab制作定时SSH自动登录和关闭的脚本
    python3 日志检索异常抛出异常 raise KeyError(key),KeyError: 'formatters'
    Pthon Matplotlib 画图
  • 原文地址:https://www.cnblogs.com/baicai37/p/13032841.html
Copyright © 2011-2022 走看看