Day 52 Django_模型层_Ajax&分页器

Ajax简介

AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步Javascript和XML”。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML,现在更多使用json数据)。

  • 同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求;
  • 异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求。
    AJAX除了异步的特点外,还有一个就是:浏览器页面局部刷新;(这一特点给用户的感受是在不知不觉中完成请求和响应过程)
    场景:

优点:

1、AJAX使用Javascript技术向服务器发送异步请求
2、AJAX无须刷新整个页面

 

基于jquery的Ajax实现

<button class="send_Ajax">send_Ajax</button>
<script>
       $(".send_Ajax").click(function(){
           $.ajax({
               url:"/handle_Ajax/",
               type:"POST",
               data:{username:"Yuan",password:123},
               success:function(data){
                   console.log(data)
               },
               
               error: function (jqXHR, textStatus, err) {
                        console.log(arguments);
                    },
               complete: function (jqXHR, textStatus) {
                        console.log(textStatus);
                },
               statusCode: {
                    '403': function (jqXHR, textStatus, err) {
                          console.log(arguments);
                     },
                    '400': function (jqXHR, textStatus, err) {
                        console.log(arguments);
                    }
                }
           })
       })
</script>

案例

1 用户名是否已被注册
在注册表单中,当用户填写了用户名后,把光标移开后,会自动向服务器发送异步请求。服务器返回true或false,返回true表示这个用户名已经被注册过,返回false表示没有注册过。客户端得到服务器返回的结果后,确定是否在用户名文本框后显示“用户名已被注册”的错误信息!
2 基于Ajax进行登录验证
用户在表单输入用户名与密码,通过Ajax提交给服务器,服务器验证后返回响应信息,客户端通过响应信息确定是否登录成功,成功,则跳转到首页,否则,在页面上显示相应的错误信息。

文件上传

一、请求头ContentType

ContentType指的是请求体的编码类型,常见的类型共有3种:

1 application/x-www-form-urlencoded
这应该是最常见的 POST 提交数据的方式了。浏览器的原生

表单,如果不设置 enctype 属性,那么最终就会以 application/x-www-form-urlencoded 方式提交数据。请求类似于下面这样(无关的请求头在本文中都省略掉了):

POST http://www.example.com HTTP/1.1
Content-Type: application/x-www-form-urlencoded;charset=utf-8

user=yuan&age=22

2 multipart/form-data
这又是一个常见的 POST 数据提交的方式。我们使用表单上传文件时,必须让

 

表单的 enctype 等于 multipart/form-data。直接来看一个请求示例:

POST http://www.example.com HTTP/1.1
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA

------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="user"

yuan
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="file"; filename="chrome.png"
Content-Type: image/png

PNG ... content of chrome.png ...
------WebKitFormBoundaryrGKCBY7qhFd3TrwA--

这个例子稍微复杂点。首先生成了一个 boundary 用于分割不同的字段,为了避免与正文内容重复,boundary 很长很复杂。然后 Content-Type 里指明了数据是以 multipart/form-data 来编码,本次请求的 boundary 是什么内容。消息主体里按照字段个数又分为多个结构类似的部分,每部分都是以 --boundary 开始,紧接着是内容描述信息,然后是回车,最后是字段具体内容(文本或二进制)。如果传输的是文件,还要包含文件名和文件类型信息。消息主体最后以 --boundary-- 标示结束。关于 multipart/form-data 的详细定义,请前往 rfc1867 查看。
这种方式一般用来上传文件,各大服务端语言对它也有着良好的支持。

上面提到的这两种 POST 数据的方式,都是浏览器原生支持的,而且现阶段标准中原生

 

表单也只支持这两种方式(通过 元素的 enctype 属性指定,默认为 application/x-www-form-urlencoded。其实 enctype 还支持 text/plain,不过用得非常少)。
随着越来越多的 Web 站点,尤其是 WebApp,全部使用 Ajax 进行数据交互之后,我们完全可以定义新的数据提交方式,给开发带来更多便利。

 

3 application/json
application/json 这个 Content-Type 作为响应头大家肯定不陌生。实际上,现在越来越多的人把它作为请求头,用来告诉服务端消息主体是序列化后的 JSON 字符串。由于 JSON 规范的流行,除了低版本 IE 之外的各大浏览器都原生支持 JSON.stringify,服务端语言也都有处理 JSON 的函数,使用 JSON 不会遇上什么麻烦。
JSON 格式支持比键值对复杂得多的结构化数据,这一点也很有用。记得我几年前做一个项目时,需要提交的数据层次非常深,我就是把数据 JSON 序列化之后来提交的。不过当时我是把 JSON 字符串作为 val,仍然放在键值对里,以 x-www-form-urlencoded 方式提交。

 

Ajax上传 json 数据

json_put.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>file_put</title>
    <script type="text/javascript" src="/static/jquery-3.4.1.js"></script>

</head>
<body>
form 表单的文件上传
<p></p>
<form action=""  method="post" enctype="multipart/form-data">
    用户:<input type="text" name="usre">
{#    头像:<input type="file" name="file" class="top">#}
    <input type="submit" id="put_file">

    <script>
        $('#put_file').click(function () {
            $.ajax({
                url:"",
                type:'post',
                contentType:"application/json",
                data:JSON.stringify({"a":1,"b":2}),
                success:function (data) {
                    console.log(data)
                }
            })
        })
    </script>
</form>
</body>
</html>

views.py

def file_put(request):
    if request.method == "POST":
        print('body',request.body)    # 请求报文中的请求体,当接收 json 时,会转为 json 格式
        print('post',request.POST)
    return render(request, 'file_put.html')

 

基于form表单的文件上传

模板部分

<form action="" method="post" enctype="multipart/form-data">
      用户名 <input type="text" name="user">
      头像 <input type="file" name="avatar">
    <input type="submit">
</form>

视图部分

def index(request):
    print(request.body)   # 原始的请求体数据
    print(request.GET)    # GET请求数据
    print(request.POST)   # POST请求数据
    print(request.FILES)  # 上传的文件数据
    return render(request,"index.html")

基于Ajax的文件上传

模板

<form>
      用户名 <input type="text" id="user">
      头像 <input type="file" id="avatar">
     <input type="button" id="ajax-submit" value="ajax-submit">
</form>

<script>

    $("#ajax-submit").click(function(){
        var formdata=new FormData();
        formdata.append("user",$("#user").val());
        formdata.append("avatar_img",$("#avatar")[0].files[0]);
        $.ajax({

            url:"",
            type:"post",
            data:formdata,
            processData: false ,    // 不处理数据
            contentType: false,    // 不设置内容类型

            success:function(data){
                console.log(data)
            }
        })
    })
</script>

视图

def index(request):
    if request.is_ajax():
        print(request.body)   # 原始的请求体数据
        print(request.GET)    # GET请求数据
        print(request.POST)   # POST请求数据
        print(request.FILES)  # 上传的文件数据
        return HttpResponse("ok")
    return render(request,"index.html")

检查浏览器的请求头:

Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryaWl9k5ZMiTAzx3FT

 

 

分页器(paginator)

 html文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>paging</title>
    <script></script>
    <link rel="stylesheet" type="text/css" href="/static/bootstrap-3.3.7-dist/css/bootstrap.css">
    <script></script>
</head>
<body>
{% for foo in current_page %}
    <ul>
        <li><span>{{ foo.name }}     </span><span>{{ foo.pawd }}</span></li>
    </ul>
{% endfor %}

{#分页栏#}
<nav aria-label="Page navigation">
    <ul class="pagination">
        {% if current_page.has_previous %}
            <li>
                <a href="?page={{ current_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 current_range %}
        {#分页栏的颜色显示#}
            {% if current_page_num == foo %}
                <li class="active"><a href="?page={{ foo }}">{{ foo }}</a></li>
            {% else %}
                <li><a href="?page={{ foo }}">{{ foo }}</a></li>
            {% endif %}

        {% endfor %}


        {% if current_page.has_next %}
            <li>
                <a href="?page={{ current_page.next_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 %}

    </ul>
</nav>

</body>
</html>

views文件

def paging(request):
    # 批量添加数据 bulk_create
    # user_list = []
    # for i in range(100):
    #     user = User(name='book%s'%i,pawd=i*i)
    #     user_list.append(user)
    # User.objects.bulk_create(user_list)
    info = User.objects.all()

    # 分页器
    paginator = Paginator(info, per_page=5)  # 分页器(分页内容,分页数量)
    # print('paginator.count:', paginator.count)  # 数据总数
    # print('num_pages:', paginator.num_pages)    # 总页数
    # print('page_range:', paginator.page_range)  # 页码的列表

    # 判断是否存在上(下)一页
    # page1 = paginator.page(6)           # 获取页码数据
    # print(page1.has_next())             # 是否有下一页  True
    # print(page1.next_page_number())     # 下一页的页码  7
    # print(page1.has_previous())         # 是否有上一页  True
    # print(page1.previous_page_number()) # 上一页的页码  5

    # 动态获取页数
    current_page_num = int(request.GET.get("page", 1))
    print(current_page_num)  # 页数

    # 固定页码显示的个数
    if paginator.num_pages > 7:
        if current_page_num - 3 < 1:
            current_range = range(1, 8)
        elif current_page_num + 4 > paginator.num_pages:
            current_range = range(paginator.num_pages - 6, paginator.num_pages + 1)
        else:
            current_range = range(current_page_num - 3, current_page_num + 4)
    else:
        current_range = paginator.page_range

    # 超出页码后默认显示第一页
    try:
        current_page = paginator.page(current_page_num)
    except EmptyPage as e:
        current_page = paginator.page(1)  # 第一页的数据

    # 显示某一页数据的两种方法
    # 方法一
    # pag = paginator.page(1)  # 第一页的数据
    # pag_1 = pag.object_list
    # print('pag_1', pag.object_list)
    #
    # # 方法二
    # for i in pag:
    #     print(i)

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

 

posted @ 2020-04-27 15:01  亦双弓  阅读(194)  评论(0编辑  收藏  举报