Django 系列博客(十四)

时间:2023-03-08 23:24:36
Django 系列博客(十四)

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)