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. 引用Excel控件时,无法嵌入互操作类型“Microsoft.Office.Interop.Excel.ApplicationClass”请改用适用的接口

    类型Microsoft.Office.Interop.Excel.ApplicationClass未定义构造函数 无法嵌入互操作类型“Microsoft.Office.Interop.Excel.Ap ...

  2. vue常用属性

    关键词:filters  | 自定义过滤器 (首字母大写) <p>{{ msg | capitalize }}</p> filters: { capitalize: funct ...

  3. 为什么导入本地jquery.js老是无效?(已解决)

    我从jquery官网里复制过来jquery.js内容,然后粘贴到本地,但是引用的时候总是无效. 在翻看脚本所在目录,无意间发现脚本文件是个jquery.js.js,    原来是我的文件的扩展名的问题 ...

  4. 关于使用freemarker导出文档的使用

    7.FreeMarker导出word文件,模板:template.ftl/** * 为word加载数据插值 * * @throws IOException */ public void exportW ...

  5. JavaScript 实现textarea限制输入字数, 输入框字数实时统计更新,输入框实时字数计算移动端bug解决

    textarea称文本域,又称文本区,即有滚动条的多行文本输入控件,在网页的提交表单中经常用到.与单行文本框text控件不同,它不能通过maxlength属性来限制字数,为此必须寻求其他方法来加以限制 ...

  6. 源码级调试的XNU内核

    i春秋翻译小组-FWorldCodeZ 源码级调试的XNU内核 无论你是在开发内核扩展,进行漏洞研究,还是还有其他需要进入macOS / iOS内核,XNU,有时你需要附加调试器.当你这样做时,使用源 ...

  7. Angularjs中的缓存以及缓存清理

    写在最前面:这篇博文是2篇文章组成,详细介绍了Angularjs中的缓存以及缓存清理,文章由上海尚学堂转载过来,欢迎大家阅读和评论.转载请注明出处,谢谢! 一个缓存就是一个组件,它可以透明地储存数据, ...

  8. Javascript高级编程学习笔记(84)—— Canvas(1)基本用法

    Canvas绘图 Canvas自HTML5引入后,由于其炫酷的效果成为HTML5新增功能中最受欢迎的部分 Canvas元素通过在页面中设定一个区域,然后就可以使用JS在其中绘制图形 <canva ...

  9. 深度学习笔记(七)SSD 论文阅读笔记简化

    一. 算法概述 本文提出的SSD算法是一种直接预测目标类别和bounding box的多目标检测算法.与faster rcnn相比,该算法没有生成 proposal 的过程,这就极大提高了检测速度.针 ...

  10. 雷达无线电系列(一)几种常见的幅度分布函数(matlab)

    文件下载地址: https://github.com/mufasa007/myblog/tree/master/%E9%9B%B7%E8%BE%BE%E6%97%A0%E7%BA%BF%E7%94%B ...