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. 3.jmeter接口测试---脚本录制

    安装好jmeter后,就要进入主题了,进行接口测试,接口测试的脚本获取方式 ①手动填写 ②badboy录制后,导入jmeter使用 ③jmeter录制 不会安装的可以进入这里:https://www. ...

  2. hadoop伪分布式搭建

    安装好jdk 减压hadoop压缩包 cd /home/hadoop/hadoop-2.7.3/etc/hadoop vi hadoop-env.sh 文件末尾处添加 jdk环境变量 export J ...

  3. error: can't copy 'docx\templates\default-docx-template': doesn't exist or not a regular file --------------- Failed building wheel for python-docx; python-docx的安装使用;python操作word

    本人第一安装python-docx很不幸就出现了,如下的错误:(如果你也遇到同样的错误,不要慌可以参考下面解决方案,由于第一次处理这种错误,如有不对欢迎大家多多批评指正) 问题所在是因为我们的setu ...

  4. jq 点击复制div里面的内容 如果粘贴到富文本中,会将样式,里面所有的标签,文字一并粘贴进去

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...

  5. mysql 删除指定字符

    mysql 删除指定字符 1.1 前言        实际需求中如果想删除指定的字符,一般需要使用到trim函数.trim函数默认删除字符的前后空格,如果想指定删除特定字符,则需要使用一下语句进行声明 ...

  6. Unity进阶----AssetBundle_03(2018/11/07)

    1. 为啥有AB包? 因为资源需要更新, 避免更新一次打包一次 动态修改. 2. AB包注意啥? 依赖关系 找依赖关系应该找到对应的平台!!! 3. 打包策略是分场景打包 若文件被文件夹包含打包出来的 ...

  7. Openstack中RabbitMQ RPC代码分析

    在Openstack中,RPC调用是通过RabbitMQ进行的. 任何一个RPC调用,都有Client/Server两部分,分别在rpcapi.py和manager.py中实现. 这里以nova-sc ...

  8. Puppeteer 应用容器化

    Puppeteer 应用容器化 Intro Puppeteer是谷歌官方出品的一个通过DevTools协议控制headless Chrome的Node库.可以通过Puppeteer的提供的api直接控 ...

  9. 【阿里聚安全·安全周刊】女主换脸人工合成小电影|伊朗间谍APP苹果安卓皆中招

    本周的七个关键词: 人工智能 丨 HTTP链接=不安全链接 丨  滑动验证码 丨 伊朗间谍APP 丨 加密挖矿 丨  Android应用测试速查表 丨 黑客销售签名证书 -1-   [人工智能]女主换 ...

  10. NeuChar 平台使用及开发教程(六):成为开发者

    在上一篇<NeuChar 平台使用及开发教程(五):使用 NeuChar 的关键字回复服务>中,我们已经学习了如何命中关键字来反馈特定格式内容的信息,这是由微信开发者/运营者自己来维护的信 ...