一.Ajax简介

在此之前你一定需要先学习下JavaScript JSON 可见:

前端学习 之 JavaScript 之 JSON

1、简单介绍

我们以前知道的前端向后端发送数据的方式有:

  GET:地址栏、a标签、Form表单

  POST:Form表单

那么现在我们在学习一种:那就是ajax

ajax:也是前端向后端发送数据的一种方式

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

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

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

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

Ajax的特点(优点)

  异步交互: 当请求发出后,浏览器还可以进行其他操作,无需等待服务器的响应!

  局部刷新:    整个过程中页面没有刷新,只是刷新页面中的局部位置而已!

二.jQuery实现Ajax

前提是在Django框架上,并已经做相关的基础配置后。

前端代码:

<body>
{% csrf_token %}
<p><input type="text" class="user" placeholder="用户名"></p>
<p><input type="password" placeholder="密码" class="pwd"></p>
<button id="ajaxTest">AJAX 测试</button>
<script src="/static/js/jquery.js"></script>
<script>
$("#ajaxTest").click(function () {
var username = $(".user").val();
var password = $(".pwd").val();
console.log(username, password);
$.ajax({
url: "/jq_ajax/",
type: "POST",
data: {
csrfmiddlewaretoken: $("input[name='csrfmiddlewaretoken']").val(),
user: username,
pwd: password,
},
success: function (res) {
alert("hahaha")
//未来接收服务端返回值,来进行做判断做的相应的反应
if (res == "ok"){
alert("okla")
}else{
alert("buok.")
}
}
})
})
</script>
</body>

后端代码:

def jq_ajax(request):

    # if request.method == "GET":

    if request.is_ajax():

        username = request.POST.get("user")

        password = request.POST.get("pwd")

        print(username, password)

        return HttpResponse("okddd")

return render(request, "jq_ajax.html")

views.py

三.Ajax案例

1.用户名是否已被注册

在注册表单中,当用户填写了用户名后,把光标移开后,会自动向服务器发送异步请求。服务器返回true或false,返回true表示这个用户名已经被注册过,返回false表示没有注册过。客户端得到服务器返回的结果后,确定是否在用户名文本框后显示“用户名已被注册”的错误信息!

2.基于Ajax进行登录验证

用户在表单输入要注册用户名,用户单击框外,网页通过Ajax提交给服务器,服务器验证用户名是否存在后返回响应信息,客户端通过响应信息做出相应的提醒,可以注册不提醒,否则在页面上显示登录用户名已经被使用!

四.Ajax实现一个计算案例

前端代码为:

<body>

<h3>计算案例</h3>

{% csrf_token %}

<input type="text" id="i1"> + <input type="text" id="i2"> = <input type="text" id="i3"> <button id="btn1">计算</button>

<span id="err"></span>

<script src="/static/js/jquery.js"></script>

<script>

$("#btn1").click(function () {

var i1 = $("#i1").val()

var i2 = $("#i2").val()

$.ajax(

{

url:"/add_test/",

type: "post",

data:{

csrfmiddlewaretoken: $("input[name='csrfmiddlewaretoken']").val(),

i1:i1,

i2:i2,

},

success : function (ret) {

{#var ret = JSON.parse(ret);   //在django后端用的是JsonResponse就不用反序列化了#}

console.log(ret,typeof ret);

if (ret.status){

$("#i3").val(ret.msg);

}else {

$("#err").text(ret.msg);

// 过三秒后自动消失

setTimeout(function () {

$("#err").text("");

},3000)

}

{#$("#i3").val(res)#}

}

}

)

})

</script>

</body>

后端django视图函数为:

from django.http import JsonResponse

import json

def add_test(request):

if request.is_ajax():

ret = {"status": 1, "msg": None}

num1 = request.POST.get("i1")

num2 = request.POST.get("i2")

try:

res = int(num1) + int(num2)

ret['msg'] = res

except ValueError as e:

ret['status'] = 0

ret['msg'] = "请核对输入的数据的合法性"

# return HttpResponse(json.dumps(ret))

//如果用到 JsonResponse就不需要序列化了

return JsonResponse(ret)

return render(request, "add_test.html")

五.基于Ajax上传json数据

1.前端模板代码

<body>

{% csrf_token %}

<h3>json 数据</h3>

<p><input type="text" class="user" placeholder="用户名"></p>

<p><input type="password" placeholder="密码" class="pwd"></p>

<button id="ajaxTest">AJAX json 测试</button>

<script src="/static/js/jquery.js"></script>

<script>

$("#ajaxTest").click(function () {

var user = $(".user").val();

var pwd = $('.pwd').val();

$.ajax({

url: "",

type: 'POST',

//注意T大写

contentType: "json",

headers: {"X-CSRFToken": $("input[name='csrfmiddlewaretoken']").val()}, // 在请求头中添加csrf

// json 前端的序列化方式

data: JSON.stringify({

user: user,

pwd: pwd,

{#csrfmiddlewaretoken: $("input[name='csrfmiddlewaretoken']").val(),#}

}),

success: function (ret) {

console.log(ret)

}

})

})

</script>

</body>

2.后端视图代码

def json_test(request):

if request.is_ajax():

print(request.POST)  # json时,post为空

print(request.body)  # 如果前端没有序列化就是原生请求体内容,如果序列化的就是字典(其实是byte类型)

data_str = request.body.decode()

data = json.loads(data_str)

print(data, type(data))  # 是字典类型

# print(data.get('user'), type(data))

return HttpResponse("ok")

return render(request, "json_test.html")

总结:

前端:

$.ajax({

url: "", # 默认往当前url提交

type: "post", #请求方式

contentType: "json",

headers: {"X-CSRFToken": $("input[name='csrfmiddlewaretoken']").val()}, // 在请求头中添加csrf

data: JSON.stringify({

key1: val1,

key2: val2,

...

},

success: function(ret){

console.log(ret)

}

})

后端:

request.POST     # 为空

request.body    # b'{"user":"alex","pwd":"123"}'

1. 转换成字符串

2. 反序列化  # dict1 = json.loads(request.body.decode())

六.基于form表单上传文件

1.前端模板代码

<body>

<h3>文件上传</h3>

<form action="" method="post" enctype="multipart/form-data">

    {% csrf_token %}

    <input type="file" name="f_name">

    <input type="submit" value="上传">

</form>

</body>

2.后端视图代码

import os

def upload(request):

if request.method == "GET":

return render(request, 'upload.html')

else:

print(request.POST)   # <class 'str'> 没有意义

# print(request.body) #  enctype="multipart/form-data"   ,会报错

print(request.FILES.get('f_name'), type(request.FILES.get('f_name')))

# 类型是一个对象

file_obj = request.FILES.get('f_name')

print(file_obj.name)

with open(os.path.join("media",file_obj.name),mode="wb") as fp:

for i in file_obj:

fp.write(i)

return HttpResponse("ok")

 七.基于Ajax请求上传文件

1.前端模板代码

<body>

<h3>ajax 文件上传</h3>

{% csrf_token %}

<input type="file" id="file_id">

<input type="button" value="上传" id="btn1">

<script src="/static/js/jquery.js"></script>

<script>

$("#btn1").click(function () {

// 封装数据

let formdata = new FormData();

formdata.append("csrfmiddlewaretoken", $("[name='csrfmiddlewaretoken']").val());

// 将f_name 传到后端当字典的键,另外一个则是一个对象

formdata.append('f_name', $("#file_id")[0].files[0]);

// 处理ajax请求

$.ajax({

url: "",

type: "POST",

processData: false,  // 告诉jQuery不要去处理发送的数据

contentType: false,  // 告诉jQuery不要去设置Content-Type请求头

data: formdata,

// 成功后返回的数据

success: function (ret) {

console.log(ret)

}

})

})

</script>

</body>

获取页面的文件对象步骤:

2.后端视图代码

def upload_ajax(request):

if request.method == "GET":

return render(request, "upload_ajax.html")

else:

print(request.POST)

# print(type(request.POST.get("fi_name1")))  #<class 'str'> 没有意义

# print(request.body)   #  enctype="multipart/form-data"   ,会报错

print(request.FILES)

print(request.FILES.get('f_name'))

print(type(request.FILES.get('f_name')))

file_obj = request.FILES.get('f_name')

print(file_obj.name)

with open(os.path.join("media", file_obj.name), "wb") as f:

for i in file_obj:

f.write(i)

return HttpResponse("ok")

后端视图代码基本和基础表单上传文件的一样。

八.ContentType 类型

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

1.application/x-www-form-urlencoded(默认类型)

    这应该是最常见的 POST 提交数据的方式了。浏览器的原生 <form> 表单,如果不设置 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=hsz&age=22

2.multipart/form-data(用于form上传文件时)

这又是一个常见的 POST 数据提交的方式。我们使用表单上传文件时,必须让 <form> 表单的 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"

hsz

------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 数据的方式,都是浏览器原生支持的,而且现阶段标准中原生 <form> 表单也只支持这两种方式(通过 <form> 元素的 enctype 属性指定,默认为 application/x-www-form-urlencoded。其实 enctype 还支持 text/plain,不过用得非常少)。

随着越来越多的 Web 站点,尤其是 WebApp,全部使用 Ajax 进行数据交互之后,我们完全可以定义新的数据提交方式,给开发带来更多便利。

3.application/json(用于json)

application/json 这个 Content-Type 作为响应头大家肯定不陌生。实际上,现在越来越多的人把它作为请求头,用来告诉服务端消息主体是序列化后的 JSON 字符串。由于 JSON 规范的流行,除了低版本 IE 之外的各大浏览器都原生支持 JSON.stringify,服务端语言也都有处理 JSON 的函数,使用 JSON 不会遇上什么麻烦。

    JSON 格式支持比键值对复杂得多的结构化数据,这一点也很有用。记得我几年前做一个项目时,需要提交的数据层次非常深,我就是把数据 JSON 序列化之后来提交的。不过当时我是把 JSON 字符串作为 val,仍然放在键值对里,以 x-www-form-urlencoded 方式提交。

Django学习 之后端视图与ajax的更多相关文章

  1. Django学习笔记(14)——AJAX与Form组件知识补充(局部钩子和全局钩子详解)

    我在之前做了一个关于AJAX和form组件的笔记,可以参考:Django学习笔记(8)——前后台数据交互实战(AJAX):Django学习笔记(6)——Form表单 我觉得自己在写Django笔记(8 ...

  2. Django学习笔记之视图高级-HTTP请求与响应

    Django限制请求method 常用的请求method GET请求 GET请求一般用来向服务器索取数据,但不会向服务器提交数据,不会对服务器的状态进行更改.比如向服务器获取某篇文章的详情. POST ...

  3. Django 学习笔记(五) --- Ajax 传输数据

    人生苦短 ~ Tips:仅适用于 Python 3+(反正差别不大,py2 改改也能用).因为据 Python 之父 Guido van Rossum 说会在 2020 年停止对 Python 2 的 ...

  4. Django学习---路由url,视图,模板,orm操作

    Django请求周期 url ->  路由系统  ->函数或者类 -> 返回字符串 或者 模板语言 Form表单提交: 点击提交 -> 进入url系统  ->  执行函数 ...

  5. Django学习路35_视图使用方法(复制的代码) + 简单总结

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

  6. Django学习日记06_视图_URLconf、View

    URLconf Django通过URLconf来响应网页请求,在项目设置settings.py中,设定了ROOT_URLCONF值来指定默认的URLconf(即mysite.urls),当HTTPRe ...

  7. Django学习笔记之视图高级-CSV文件生成

    生成CSV文件 有时候我们做的网站,需要将一些数据,生成有一个CSV文件给浏览器,并且是作为附件的形式下载下来.以下将讲解如何生成CSV文件. 生成小的CSV文件 这里将用一个生成小的CSV文件为例. ...

  8. Django学习笔记之视图高级-类视图

    类视图 在写视图的时候,Django除了使用函数作为视图,也可以使用类作为视图.使用类视图可以使用类的一些特性,比如继承等. View django.views.generic.base.View是主 ...

  9. Django学习之 - 基础视图函数

    视图:Views 获取用户请求的方法: 1: request.GET 2: request.POST 3: request.FILES # checkbox 等多选文件 4:request.POST. ...

随机推荐

  1. 【代码学习】PYTHON 闭包

    一.闭包 在函数内部再定义一个函数,并且这个函数用到了外边函数的变量 在函数里定义一个函数,不会默认被执行 def test(number): print("-----1-----" ...

  2. Go语言基础之rand(随机数)包

    在Golang中,有两个包提供了rand,分别为 "math/rand" 和 "crypto/rand",  对应两种应用场景. "math/rand ...

  3. 安装RabbitMQ,一直提示Erlang版本过低

    1.背景 windows系统,控制面板卸载Erlang后,重新安装Erlang成功,当再安装RabbitMQ时,报如下提示: 意思就是说Erlang版本过低,请安装更高的版本. 出现上面问题的原因,是 ...

  4. 图片识别OCR:

    使用Python制作一个简易的OCR图片文字识别工具:键盘上的PrtScr按键+画图工具+百度AI图片识别(账户,调用接口)+python 常见的OCR工具: 1. Microsoft Onenote ...

  5. 【PAT甲级】1096 Consecutive Factors (20 分)

    题意: 输入一个int范围内的正整数,输出它最多可以被分解为多少个连续的因子并输出这些因子以*连接. trick: 测试点5包含N本身是一个素数的数据,此时应当输出1并把N输出. 测试点5包含一个2e ...

  6. 【CSS属性#1】

    " 目录 一.宽和高 二.字体属性 1. 文字字体 font-famlly 2. 字体大小 font-size 3. 字重(粗细) font-weight 4. 文本颜色 color 三.字 ...

  7. java redis 实现用户签到功能(很普通简单的签到功能)

    业务需求是用户每天只能签到一次,而且签到后用户增加积分,所以把用户每次签到时放到redis 缓存里面,然后每天凌晨时再清除缓存,大概简单思想是这样的 直接看代码吧如下 @Transactional @ ...

  8. python 爬取图片

    使用python的requests库爬取网页时,获取文本一般使用text方法,如果要获取图片并保存要用content 举个栗子,爬煎蛋网的图: #!/usr/bin/env python #-*- c ...

  9. 「NOIP2018」赛道修建

    传送门 Luogu 解题思路 一眼先二分(上界树的直径,下界最小边权),然后再考虑 \(\text{DP}\). 对于当前节点 \(u\),在它的所有儿子中分别返回一条匹配不完的长度最大的路径 \(M ...

  10. php 单机redis 常用命令

    一.Redis连接与认证 //连接参数:ip.端口.连接超时时间,连接成功返回true,否则返回false $ret = $redis->connect('127.0.0.1', 6379, 3 ...