python-Django与ajax实现前后端交互, 局部刷新, 序列化类serializers

python-Django与ajax实现前后端交互, 局部刷新

**一 什么是Ajax **

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

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

AJAX除了异步的特点外,还有一个就是:浏览器页面局部刷新;(这一特点给用户的感受是在不知不觉中完成请求和响应过程)

这样就不用对整个网页进行刷新, 即可更新数据.

使用场景:

用户注册或选项中

实时验证

优点:

  • ajax使用JavaScript技术向服务器发送异步请求
  • 无需刷新页面即可得到更好的提示效果

那么是怎么实现的呢

基于jquery的ajax实现前后端交互

先简单的实现一个交互

这里只写前端js代码, 后续补上全部代码
<script src="/static/jQuery/jQuery.min.js"></script>
<script>
    $("#btn").click(function () {
        $.ajax({
            url:"/提交地址/",
            method:'post',  //以post方法提交
            data:{         //携带数据
                username:"用户名",
                password:"密码"
            },
            success:function (data) {  // 正确返回结果
                console.log(data)  // 打印到控制台
            },
            error:function (data) {   // 请求不到数据或数据不存在返回结果
                console.log(data)
            }
        })
    })
</script>

ajax执行流程

完整案例

实现一个局部向服务器提交数据,得到结果后动态局部填充

代码实现如下

简单的请求响应, # GET 请求返回静态界面, # 判断是否为ajax请求, 不是返回请求无效

view视图
from django.shortcuts import render
from django.http import JsonResponse
def test_ajax(request):
    # 
    if request.method == "GET":
        return render(request, 'index.html')
    
    res = {"code": 101, "msg": "请求无效"}
    # 
    if request.is_ajax():
        rest = request.POST
        s1 = int(rest.get("con1"))
        s2 = int(rest.get("con2"))
        s3 = s1 + s2
        res["msg"] = s3
    return JsonResponse(res)  // 成功与否都返回json数据格式

路由, 只要一个路由, get,post都走这个

urlpatterns = [
    ...
    path("ajax-add/", views.test_ajax),
]

HTML界面, 这里使用的是 jquery方法,使用前需要导入jquery, 代码中有详细解释, 请 耐心看完

<script src="/static/jQuery/jQuery.min.js"></script>
# 显示输入框, 
<div>
    <input type="text" id="cont1"> +
    <input type="text" id="cont2"> =
    <input type="text" readonly id="total">
</div>
<br>
<input type="submit" class="btn-primary" id="sub">

jquery实现代码
<script>
    $("#sub").click(function () {
        $.ajax({
            url:"/ajax-add/",  // 请求路由, 向ajax-add地址发送请求
            method:"post",     // 请求方式, 可以指定多种请求方式, 这里使用post请求
            data:{             // 请求携带数据, 
                con1:$("#cont1").val(),  // 根据标签中的id取值
                con2:$("#cont2").val()
            },
            success:function (data) {   // 成功后执行该函数, 否则不执行
                $("#total").val(data.msg) // 给id为total标签添加请求成功后返回数据
            }
        })
    })
</script>

2 基于ajax进行注册验证

一个简单的ajax请求已经了解, 接下来实现注册时提示功能

用户在表单输入用户名与密码,通过Ajax提交给服务器,服务器验证后返回响应信息,客户端通过响应信息确定是否注册成功,成功,则跳转到登录页面,否则,在页面上显示相应的错误信息

代码如下

视图, 这是就需要两个路由了 , 因为检查用户是否存在和提交真实用户注册数据都是post请求, 需要单独写路由, 如果多一点判断也是可以实现的, 这里就简单的写了

提交信息函数
def register(request):
    # GET 请求返回静态界面
    if request.method == "GET":
        return render(request, 'index.html')

    res = {"code": 101, "msg": "请求无效"}
    # 判断是否为ajax请求, 不是返回请求无效
    if request.is_ajax():
        rest = request.POST
        // 存储数据
        try:
            models.User.objects.create(name=rest.get("username"), password=rest.get("password"))
            res["code"] = 100
            res["msg"] = '注册成功'
        except Exception:
            res["msg"] = '提交信息有误'
    return JsonResponse(res)


检查用户是否存在
def check(request):
    res = {"code":101, "msg":"用户名可用"}

    username = request.POST.get("username")
    user = models.User.objects.filter(name=username).count()
    if user:
        res["msg"] = '该用户已存在'
    return JsonResponse(res)


路由
urlpatterns = [
	...
    path("register/", views.register),
    path("check/", views.check)
]

HTML代码

注: 需要先导入bootstrap.min.cssjQuery.min.js

页面显示代码
<div  class="center-block">

  <div class="form-group">
    <label for="bt">账号</label>
    <input type="text" class="form-control" placeholder="请输入账号" id="bt">
      <span id="count" class="pull-right"></span>
  </div>
  <div class="form-group">
    <label for="bs">密码</label>
    <input type="password" class="form-control" placeholder="请输入密码" id="bs">

  </div>
        <span id="password"></span>
  <button type="button" class="btn btn-primary" id="btn">注册</button>

</div>

js代码, 代码分为两段, 一个是检验用户, 单独写, 当鼠标移开input框后发送ajax请求验证数据

有则提示用户已经存在

没有则提示可以注册

<script>
    // 鼠标移开input框后提交数据验证
    $("#bt").blur(function () {
        $.ajax({
            url:"/check/",
            method:"post",
            data:{
                username:$("#bt").val(),
            },
            success:function (data) {
                if (data.code === 100){
                    $("#password").html(data.msg)

                    // 跳转登录页面
                    // location.href = '/login/'
                }
                else {
                    $("#count").html(data.msg)
                }
            }
        })
    })
	// 点击后提交真实数据
    $("#btn").click(function () {
        $.ajax({
            url:"/register/",
            method:"post",
            data:{
                username:$("#bt").val(),
                password:$("#bs").val()
            },
            success:function (data) {
                $("#password").text(data.msg)
            }
        })
    })
</script>

成功后如图

下面完成最后的ajax提交文件, 前面已经写过篇, 为使用js动态显示头像, 这里是使用 ajax 提交图片或文件数据到后台

文件上传

请求头ContentType

1 application/x-www-form-urlencoded

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

后续的HTML页面就不粘贴到这里了, 都是根据id取值, 懂得都懂

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

user=lqz&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 方式提交。

基于Form表单上传文件

<form action="/file_put/" method="post" enctype="multipart/form-data">
    用户名:<input type="text" name="name">
    头像:<input type="file" name="avatar" id="avatar1">
<input type="submit" value="提交">
</form>

必须指定 enctype="multipart/form-data"

视图函数

def file_put(request):
    if request.method=='GET':
        return render(request,'file_put.html')
    else:
        # print(request.POST)
        # print(request.POST)
        print(request.body)  # 原始的请求体数据 
        print(request.GET)  # GET请求数据 
        print(request.POST)  # POST请求数据 
        print(request.FILES)  # 上传的文件数据
        # print(request.body.decode('utf-8'))
        print(request.body.decode('utf-8'))

        print(request.FILES)
        file_obj=request.FILES.get('avatar')
        print(type(file_obj))
        with open(file_obj.name,'wb') as f:
            for line in file_obj:
                f.write(line)
        return HttpResponse('ok')

基于Ajax上传文件

$("#ajax_button").click(function () {
        var formdata=new FormData()
        formdata.append('name',$("#id_name2").val())
        formdata.append('avatar',$("#avatar2")[0].files[0])
        $.ajax({
            url:'',
            type:'post',
            processData:false, //告诉jQuery不要去处理发送的数据
            contentType:false,// 告诉jQuery不要去设置Content-Type请求头
            data:formdata,
            success:function (data) {
                console.log(data)
            }
        })
    })

浏览器请求头为:

Content-Type:

multipart/form-data; boundary=----WebKitFormBoundaryA5O53SvUXJaF11O2

五 Ajax提交json格式数据

$("#ajax_test").click(function () {
        var dic={'name':'lqz','age':18}
        $.ajax({
            url:'',
            type:'post',
            contentType:'application/json',  //一定要指定格式 contentType: 'application/json;charset=utf-8',
            data:JSON.stringify(dic),    //转换成json字符串格式
            success:function (data) {
                console.log(data)
            }
        })
    })

提交到服务器的数据都在 request.body 里,取出来自行处理

六 Django内置的serializers(把对象序列化成json字符串)

from django.core import serializers
def test(request):
    book_list = Book.objects.all()    
    ret = serializers.serialize("json", book_list)
    return HttpResponse(ret)
//转换成json字符串格式
            success:function (data) {
                console.log(data)
            }
        })
    })

提交到服务器的数据都在 request.body 里,取出来自行处理

六 Django内置的serializers(把对象序列化成json字符串)

from django.core import serializers
def test(request):
    book_list = Book.objects.all()    
    ret = serializers.serialize("json", book_list)
    return HttpResponse(ret)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值