Django 系列博客(十四)

前言

本篇博客介绍在 html 中使用 ajax 与后台进行数据交互。

什么是 ajax

ajax(Asynchronous Javascript And XML)翻译成中文就是‘’异步 JavaScript 和 XML‘’。即使用 JavaScript 语言与服务器进行异步交互,传输的数据为 XML(现在更多地使用 json)。

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

ajax 除了异步的特点外,还有一个就是:浏览器页面局部刷新。在页面没有进行刷新的情况下进行数据交互。

优点:

  • ajax 使用JavaScript 技术向服务器发送异步请求;
  • ajax 无需刷新整个页面。

基于 jQuery 的 ajax 实现

前端代码

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="/static/jquery-3.3.1.js"></script> <title>regist</title>
{# <link rel="stylesheet" href="/static/jquery-3.3.1.js">#}
</head>
<body>
<p>用户:<input type="text" id="name"></p>
<p>密码:<input type="password" id="pwd"></p>
<p>确认密码:<input type="password" id="tpwd"></p>
<input type="button" id="submit" value="提交"><span id="error"></span>
</body> <script> $('#submit').click(function () {
console.log($('#submit'));
{#$.ajax({#}
{# url:'/regist/',#}
{# type:'post',#}
{# data:{name:$("#name").val(), pwd:$("#pwd").val(), tpwd:$("#tpwd")},#}
{# success:function (data) {#}
{# console.log(data)#}
{# }#}
$.ajax({
url:'/regist/',
type:'post',
data:{name:$("#name").val(), pwd:$("#pwd").val(), tpwd:$("#tpwd").val()},
success:function (data) {
console.log(data)
}
}) })
</script>
</html>

后端代码

from django.http import JsonResponse
from django.shortcuts import render, redirect
from app01.models import * # Create your views here. def wrapper(func):
def inner(*args, **kwargs):
if args[0].method == 'GET':
return func(*args, **kwargs)
elif kwargs['contentType'] == 'application/json':
import json
args[0].POST = json.loads(args[0].body)
return func(*args, **kwargs)
else:
return func(*args, **kwargs)
return inner import json
# json.loads() def regist(request):
dic = {'status': 200, 'msg': None}
print(request.body)
if request.method == 'GET':
return render(request, 'regist.html')
else:
print('/////')
print(request.POST, 'dddd')
name = request.POST.get('name')
pwd = request.POST.get('pwd')
tpwd = request.POST.get('tpwd') user = UserInfo.objects.filter(name=name).first()
if user:
dic['status'] = 100
dic['msg'] = '用户已存在'
return JsonResponse(dic)
else:
if name and pwd and tpwd:
if pwd == tpwd:
UserInfo.objects.create(name=name, pwd=pwd)
dic['msg'] = '注册成功'
return JsonResponse(dic)
else:
dic['status'] = 101
dic['msg'] = '两次密码不一样'
return JsonResponse(dic)
else:
dic['status'] = 101
dic['msg'] = '密码不正确'
return JsonResponse(dic) @wrapper
def login(request):
dic = {'status': 200, 'msg': None}
if request.method == 'GET':
return render(request, 'login.html')
else:
name = request.POST.get('name')
pwd = request.POST.get('pwd') user = UserInfo.objects.filter(name=name).first()
if not user:
dic['status'] = 100
dic['msg'] = '用户不存在,请注册'
return JsonResponse(dic)
else:
if pwd == user.pwd:
dic['msg'] = '登陆成功'
return JsonResponse(dic)
else:
dic['status'] = 101
dic['msg'] = '密码错误'
return JsonResponse(dic)

js代码

$("#submit3").click(function () {
$.ajax({
url: '/auth/',
type: 'post',
data: {
'user': $("#id_name").val(),
'password': $('#id_password').val()
}, success: function (data) {
{#console.log(data)#}
var data=JSON.parse(data)
if (data.user){
location.href='https://www.baidu.com'
}else {
$(".error").html(data.message).css({'color':'red','margin-left':'20px'})
}
} })
}
)

文件上传

请求头

  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 请求体
  1. multipart/form-data

当我们使用表单上传文件时,必须让表单的 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--表示结束。

这种方式一般用于上传文件,各大服务端语言也有很好的支持。

这两种POST 提交的方式,都是浏览器原生支持的,而且先阶段标准中原生表单也只支持这两种方式(通过元素的 enctype 属性指定,默认为 application/x-www-form-urlencoded)。随着越来越多的web站点尤其是 WebApp,全部使用 Ajax 进行数据交互之后,我们完全可以定义新的数据提交方式,给开发带来更多便利。

  1. application/json

application/json是另外一种请求头,不过更多的是作为响应头,因为 json 格式的数据时通用数据格式。不过目前也用来作为请求头,用来告诉服务器端主体是序列化后的 json 字符串。由于 json 规范的流行,除了低版本的 IE 之外的各大浏览器都原生支持 json.stringfy,服务器端语言也都有处理 json数据的函数,使用 json 不会遇到什么麻烦。

json 格式支持比键值对复杂的多的结构化数据,这点对数据传输很有用。

基于form表单上传文件

前端代码

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body> <form action="" method="post" enctype="multipart/form-data">
<p>用户名:<input type="text" name="name"></p>
<input type="file" name="myfile">
{# <input type="file" name="myfile2">#}
<input type="submit" value="提交"> </form> </body>
</html>

后端代码

class UploadFile(View):

    def get(self, request):
return render(request, 'upload_file.html') def post(self, request):
file = request.FILES.get('myfile')
# print(file['file'])
from django.core.files.uploadedfile import InMemoryUploadedFile
print(time.time())
filename = str(time.time()).split('.')[0] + file.name
with open(filename, 'wb') as f:
for line in file:
f.write(line)
return HttpResponse('上传成功')

基于ajax 的文件上传

前端代码

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>uploadfile</title>
<script src="/static/jquery-3.3.1.js"></script>
</head>
<body>
<p>用户名:<input type="text" id="name"></p>
<p>选择文件:<input type="file" id="my_file"></p>
<button id="btn">上传</button><span id="msg"></span>
</body> <script>
$('#btn').click(function () {
var myfile = $('#my_file')[0].files[0];
var formdata = new FormData();
formdata.append('name', $('#name').val());
formdata.append('myfile', myfile);
$.ajax({
url:'/uploadfile/',
type:'post',
processData:false, // 告诉 jQuery 不要处理发送的数据
contentType:false, // 告诉 jQuery 不要设置 Content-Type 请求头
data:formdata,
success:function (data) {
console.log(data);
$('#msg').text(data)
}
})
}) </script>
</html>

后端代码

MEDIA_PATH = '/Users/jingxing/Django/homework/paging/media'

def uploadfile(request):
if request.method == 'GET':
return render(request, 'uploadfile.html')
else: myfile = request.FILES.get('myfile')
print(myfile)
filepath = os.path.join(MEDIA_PATH, myfile.name[32:-3]+'jpg')
with open(filepath, 'wb') as f:
for line in myfile:
f.write(line)
FileInfo.objects.create(name=request.POST.get('name'), filepath=filepath)
return HttpResponse('上传成功')

ajax 提交 json 格式数据

前端代码

$('#submit1').click(function () {
postdata={name1:$("#name").val(),pwd2:$("#pwd").val()}
$.ajax({
url:'/loginjson/',
type:'post',
// 指定提交的编码格式是json格式,
contentType:'application/json',
data:JSON.stringify(postdata),
// data:postdata,
// data:'123',
success:function (data) {
console.log(data) }
})
})

后端代码

def loginjson(request):
dic={'status':100,'msg':None}
if request.method=='POST':
print(request.POST)
print(request.GET)
print(request.body)
xx=request.body.decode('utf-8')
# re是个字典{"name1":"lqz","pwd2":"123"}
re=json.loads(xx)
request.POST=11 print(request.POST)
#
#
# name=re.get('name1')
# pwd=re.get('pwd2')
# print(name)
# print(pwd)
return HttpResponse('ok')

后端返回 json 数据

前端代码

$('#submit').click(function () {
$.ajax({
url:'/login/',
type:'post',
data:{name1:$("#name").val(),pwd2:$("#pwd").val()},
success:function (data) {
//后台用JsonResponse返回数据
//data 就会被转成字典
console.log(data)
console.log(typeof data)
//JSON.parse(data) 把字符串类型转成字典
data=JSON.parse(data)
{#JSON.stringify()#}
console.log(typeof dat1)
if(data.status == 100){
//成功,跳转到指定页面
//location.href=地址,前端就会跳转到指定的url
alert(data.msg)
//$("#error").text(data.msg+'正在跳转')
//location.href=data.url
}else{
$("#error").text(data.msg)
} }
})
})

后端代码

def login(request):
dic={'status':100,'msg':None}
if request.method == 'GET':
return render(request, 'login.html')
# if request.is_ajax():
if request.method=='POST':
name=request.POST.get('name1')
pwd=request.POST.get('pwd2')
if name=='lqz' and pwd=='123':
dic['msg'] = '登陆成功'
# 想让前端跳转
# dic['url']='http://www.baidu.com'
dic['url']='/test/'
else:
# 返回json格式字符串
dic['status']=101
dic['msg']='用户名或密码错误'
# return JsonResponse(dic)
return HttpResponse(json.dumps(dic))

Django内置的序列化数据方法

from django.core import serializers

def test(request):
book_list = Book.objects.all()
ret = serializers.serialize('json', book_list)
return HttpResponse(ret)

Django 系列博客(十四)的更多相关文章

  1. Django 系列博客(四)

    Django 系列博客(四) 前言 本篇博客介绍 django 如何和数据库进行交互并且通过 model 进行数据的增删查改 ORM简介 ORM全称是:Object Relational Mappin ...

  2. Django 系列博客(十六)

    Django 系列博客(十六) 前言 本篇博客介绍 Django 的 forms 组件. 基本属性介绍 创建 forms 类时,主要涉及到字段和插件,字段用于对用户请求数据的验证,插件用于自动生成 h ...

  3. Django 系列博客(十二)

    Django 系列博客(十二) 前言 本篇博客继续介绍 Django 中的查询,分别为聚合查询和分组查询,以及 F 和 Q 查询. 聚合查询 语法:aggregate(*args, **kwargs) ...

  4. Django 系列博客(十)

    Django 系列博客(十) 前言 本篇博客介绍在 Django 中如何对数据库进行增删查改,主要为对单表进行操作. ORM简介 查询数据层次图解:如果操作 mysql,ORM 是在 pymysql ...

  5. Django 系列博客(一)

    Django 系列博客(一) 前言 学习了 python 这么久,终于到了Django 框架.这可以说是 python 名气最大的web 框架了,那么从今天开始会开始从 Django框架的安装到使用一 ...

  6. Django搭建博客网站(四)

    Django搭建博客网站(四) 最后一篇主要讲讲在后台文章编辑加入markdown,已经在文章详情页对markdown的解析. Django搭建博客网站(一) Django搭建博客网站(二) Djan ...

  7. Django 系列博客(十三)

    Django 系列博客(十三) 前言 本篇博客介绍 Django 中的常用字段和参数. ORM 字段 AutoField int 自增列,必须填入参数 primary_key=True.当 model ...

  8. Django 系列博客(十一)

    Django 系列博客(十一) 前言 本篇博客介绍使用 ORM 来进行多表的操作,当然重点在查询方面. 创建表 实例: 作者模型:一个作者有姓名和年龄. 作者详细模型:把作者的详情放到详情表,包含生日 ...

  9. Django 系列博客(九)

    Django 系列博客(九) 前言 本篇博客介绍 Django 模板的导入与继承以及导入导入静态文件的几种方式. 模板导入 模板导入 语法:``{% include '模板名称' %} 如下: < ...

随机推荐

  1. IIS 接口访问404

    IIS->网站->ASP->启用父路径(true)

  2. gym 101628

    前几天感冒了三天没怎么写题...今天好很多了打个三星场找点手感. 不行啊我好菜啊.只会8个..补题的话,再说吧.G题感觉值得一补. 补了G,K不想写B不会. 说实话这个三星场还是很新人向的,知识点也蛮 ...

  3. ssm知识点整理

    第1章 resultType和resultMap的区别是什么?  MyBatis中在查询进行select映射的时候,返回类型可以用resultType,也可以用resultMap,resultType ...

  4. js原型与继承

    demofunction Fun(){}
var foo = new Fun();foo.__proto__ === Fun.prototype 摘要 1.js本身不提供类实现,es6引入了class ...

  5. k8s probe

    livenessProbe: httpGet: path: /abc/401 port: 8384 scheme: HTTP

  6. ubuntu connect to windows folder share

    在windows上给远程登录的用户设置一个账号密码.”右击计算机图标“——"管理”——“本地用户和组”——“用户”.然后右击选择“新用户”,输入账号密码,并勾选“密码永不过期”,这样,在远程 ...

  7. 电子科技大学实验中学PK赛(二)比赛题解

    比赛地址:http://qscoj.cn/contest/27/ A题 FIFA强化 分析:这个题目要求说的比较明显,用几个if判断一下就好了.不要一判断完就输出,最好用一个ans储存下答案.输出答案 ...

  8. 使用 TRESTClient 與 TRESTRequest 作為 HTTP Client 之二 (POST 檔案)

    使用 HTML 进行文件上传,已经是很平常的应用了,在手机App里面,也常常会用到这个作业,例如拍照上传,或是从相簿选取照片上传,都是很常见的. 在 HTML 的 Form 里面,要让使用者选择文件上 ...

  9. JAVA小白开发环境配置(编译器为Idea)

    JDK配置 1.首先到官网下载最新版JDK:Oracle官网下载 Accept License Agreement–>下载适合自己pc版本的jdk(此处以64位windows为例.x86是32位 ...

  10. numpy.random 常用函数详解之排列乱序篇(Permutations)

    1.numpy.random.shuffle(x) 参数:填入数组或列表. 返回值:无. 函数功能描述:对填入的数组或列表进行乱序处理,shape保持不变. 2.numpy.random.permut ...