Django09Ajax介绍
JsonResponse复习下。
一:Ajax介绍
AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。
即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML,现在更多使用json数据)。
AJAX 不是新的编程语言,而是一种使用现有标准的新方法。
AJAX 是与服务器交换数据并更新部分网页的艺术,在不重新加载整个页面的情况下。
- 异步:请求发出去,不会卡在这,可以干其他事。
- 局部刷新:js的dom操作,使页面局部刷新。
- 基本上web页面都有很多ajax请求。
1.什么是Ajax?
AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步Javascript和XML”。
- 异步:和同步对应;
- JavaScript:通过JavaScript来操作,发送请求到服务端;
- XML:数据交互使用XML,现在主流使用JSON格式;
- 局部刷新:JS的DOM操作。
刚发明的时候穿的是XML后来截至目前21世纪20年代前后兴起用json格式。
即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML,现在更多使用json数据)。
AJAX 是一种用于创建快速动态网页的技术。
通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
传统的网页(不使用 AJAX)如果需要更新内容,必需重载整个网页面。
有很多使用 AJAX 的应用程序案例:新浪微博、Google 地图、开心网等等。
❗ AJAX应用程序与浏览器和平台无关的!
2.同步与异步
- 同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求;
- 异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求。
3.XML格式与JSON格式
XML格式:
<name>BAOBAO</name>
<age>18</age>
<gender>male</gender>
JSON格式:
{
"name": "Darker",
"age": "18",
"gender": "male",
}
对比:
格式 | 可阅读性 | 解析难度 | 空间占用 |
---|---|---|---|
XML | 高 | 复杂 | 大 |
JSON | 高 | 简单 | 小 |
Ajax--->服务器---->Ajax执行流程图
写ajax跟后端交互
1 使用原生js写ajax请求(没有人用)
- 第一:麻烦;
- 第二:区分浏览器,需要做浏览器兼容。
2 现在主流做法(现成有人封装好了,jquery,axios..)
前后端分离开发主流用Ajax。
前后端混合开发用jQuery。(公司几乎不用原生js)
- 以jquery为例讲;
- 后面会讲axios。
1 ajax发送其他请求
1 大坑
-如果在form表单中,写button和input是submit类型,会触发form表单的提交
-如果不想触发:
-不写在form表单中
-使用input,类型是button
2 坑
-后端响应格式如果是:html/text格式,ajax接收到数据后需要自己转成对象
-后端响应格式是:json,ajax接收到数据后会自动转成对象
-总结:后端返回数据,统一都用JsonResponse、
3 坑
-如果使用了ajax,后端就不要返回rediret,render,HttpResponse
-直接返回JsonResponse
二:Ajax的简单使用
原生JS可以写Ajax请求的,但是写起来很复杂,而且需要考虑浏览器的版本(不推荐使用)
JQuery已经封装了1个ajax方法,直接调用JQuery,就可以发送Ajax请求
前后端分离的项目,依旧可以使用JQuery的ajax,但是axios更加主流一些
本质:通过JS发送HTTP请求(异步请求)
基本格式
$ 是jQuery对象;写在script标签内。
$.ajax({
url: '/add/', //ajax请求的地址
method: 'post', # 指定请求方式
data: {
'a': $('#first').val(), //取到first的值
'b': $('#second').val(), //取到second的值
},
success: function (data) { // success:函数(形参)
// 成功后 触发
},
error: function () {
// 失败后 触发
}
})
-
$.ajax() # 相当于jQuery提供了Ajax函数;括号内传参数。
-
上面$.ajax() 中传的参数是对象类型用 key:vlaue 形式。
-
data 是数据形式key:value形式,js中key可以不加引号 “ ”。
实例一:ajax实现计算
1.需求
- 页面三个输入框和一个''计算''按钮
- 在前两个输入框内输入数字, 点击计算按钮, 在第三个输入框内动态展示前两数字乘积
- 使用Ajax向后端提交请求, 页面不能进行刷新
- 计算必须在后端进行
后端views.py
def ajax_test(request):
return render(request,'ajax_test.html')
def sum(request):
import time
time.sleep(2)
a1=int(request.GET.get('a1'))
a2=int(request.GET.get('a2'))
return HttpResponse(a1+a2)
前端ajax_test.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>计算</title>
<script src="/static/jquery-3.3.1.js"></script>
</head>
<body>
<input type="text" id="a1"> + <input type="text" id="a2">=<input type="text" id="sum">
<button id="btn_submit">计算</button>
</body>
<script>
// 设置点击事件
$('#btn_submit').click(function () {
var a1 = $('#a1').val() //取到a1的值
var a2 = $('#a2').val() //取到a2的值
// 发送ajax请求,计算,返回结果
$.ajax({
url: '/sum1/', //ajax请求的地址,这里和url中要一致。指定后端地址,不指定则提交到当前地址。
method: 'get',//请求方式,不指定默认get
data: {'a1': a1, 'a2': a2}, //携带参数;需要发送的数据。
// 回调函数:后端返回结果的时候自动触发,并将结果传给args
success:function (data) { //服务端成功返回会回调,执行匿名函数
console.log(data)
$('#sum').val(data)
}
})
})
</script>
</html>
路由urls.p
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^ajax/', views.ajax),
url(r'^sum1/', views.sum),
]
实例二:ajax实现计算
效果:
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>计算</title>
<link rel="stylesheet" href="/static/bootstrap/css/bootstrap.css">
<script src="/static/js/jquery-3.5.1.min.js"></script>
</head>
<body>
<div class="container-fluid">
<div class="row">
<div class="col-md-6 col-lg-offset-3" style="margin-top: 100px;">
<input type="text" id="first"> +
<input type="text" id="second"> =
<input type="text" id="sum">
<button class="btn btn-success btn-sm" id="btn">计算</button>
</div>
</div>
</div>
<script>
$('#btn').click(function () {
$.ajax({
url: '/add/', // 向哪个地址发送请求
method: 'post', // 发送什么请求
// 使用jQuery获取输入框内的值
// data:向后端传输的数据(没有指定编码,就默认使用urlencoded)
data: {
'a': $('#first').val(),
'b': $('#second').val(),
},
success: function (data) {
// 数据正常返回,就会触发该匿名函数的执行,返回的数据就会赋值给data
console.log(data)
// 把后端返回的数据,通过DOM操作,返回到框中
$('#sum').val(data)
},
error: function () {
// 失败,会触发这个
console.log('出错了')
}
})
})
</script>
</body>
</html>
views.py
from django.shortcuts import render, HttpResponse
def index(request):
return render(request, 'index.html')
def add(request):
# request.is_ajax(): 判断是否是ajax请求
if request.method == 'POST':
a = int(request.POST.get('a'))
b = int(request.POST.get('b'))
print(a, b)
return HttpResponse(a + b)
urls.py
urlpatterns = [
path('', views.index),
path('add/', views.add),
]
实例三:ajax实现认证后跳转
ajax能不能自动解析取决于响应头的类型;例如:
# return HttpResponse(json.dumps(response)) # 转成json格式发送到前端
# 返回的head头的'content_type'是html格式;
return JsonResponse(response) # 用json格式发送到前端;JsonResponse源码中已经用到了json.dumps功能
# 返回的head头的'content_type'是jsonapplication/json格式;ajax会自动解析p
准备数据库表:记得迁移
class User(models.Model):
name = models.CharField(max_length=16, verbose_name='用户名')
password = models.CharField(max_length=16, verbose_name='密码')
def __str__(self):
return self.name
迁移后再继续写
urls.py
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^login/', views.login),
]
views.py
from django.shortcuts import render, HttpResponse, redirect
from django.http import JsonResponse
# Create your views here.
from app01 import models
import json
def login(request):
if request.method == 'GET': # 判断请求方式若是GET
return render(request, 'login.html')
elif request.is_ajax(): # 判断是不是ajax请求
response = {'status': 100, 'msg': None} # 定义一个响应的字典
name = request.POST.get('username') # 取出name字段
password = request.POST.get('password')
user = models.User.objects.filter(name=name, password=password).first() # 拿提交来的用户+密码到数据表中进行查询
if user: # 查到了说明是有的。
# 用户名和密码都对了
# return redirect('') 出错,不可以用redirect重定向
response['msg'] = "登录成功"
else:
response['status'] = 101
response['msg'] = '用户名或密码错误'
# return HttpResponse(json.dumps(response)) # 转成json格式发送到前端
# 返回的head头的'content_type'是html格式;
return JsonResponse(response) # 用json格式发送到前端;JsonResponse源码中已经用到了json.dumps功能
# 返回的head头的'content_type'是jsonapplication/json格式;ajax会自动解析
login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录认证+跳转</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
</head>
<body>
<p> 用户名:<input type="text" id="id_name"></p>
<p> 密码:<input type="password" id="id_password"></p>
<button id="id_btn">提交</button>
<span class="error" style="color: red"></span>
</body>
<script>
$('#id_btn').click(function () {
$.ajax({
url: '/login/',
method: 'post',
// username=bao&password=123
data: {username: $('#id_name').val(), password: $('#id_password').val()},
success: function (data) {
//如果ajax拿到响应是json格式字符串自动转成对象;ajax认为是字符串则需手动转
// res=JSON.parse(data)
//console.log(data)
//console.log(res)
// data 现在是对象类型(因为用jsonresponse)
if (data.status === 100) {
//登录成功,重定向到百度,前端重定向
location.href = 'http://www.baidu.com'
//location.href='/index/' //这是前端重定向,匹配自己的网页时用文件名即可,http会自己补上。
} else {
//登录失败
//$('.error').html(data.msg).css({'color':'red'}) //.css设置颜色,span标签写过了这里就不写了
$('.error').html(data.msg) //取到spn标签的error向标签内写提示;
}
},
error: function (data) { # 请求出错会到这里来
console.log(data)
}
})
})
</script>
</html>
前后端数据传输的编码格式
模板层第一节也提到过
1.前端中可以向后端发起post请求的方式
- form 表单
- ajax 请求
2.基于post请求, 前后端数据传输的主流编码格式有三种
- urlencoded : 默认的编码格式, 提交的数据从
request.POST
中提取 - form-data : 上传文件时使用的编码格式, 提交的数据从
request.POST
中提取, 上传的文件从request.FILES
中提取 - json : ajax发送的json格式数据, 在
request.POST
中取不到数据, 需要在request.body
中提取数据
3.基于post请求, form表单传输数据默认的编码格式
- 默认编码格式为 : urlencoded
- 如果要上传文件需要在标签中指定 : enctype="multipart/form-data" 编码格式
- 数据格式 : username=shawn&password=1111
- 提交位置 : django后端针对符合urlencoded编码格式的数据都会自动帮你解析封装到request.POST中, 文件提交到
request.FILES
中。
4.基于post请求, ajax传输数据默认编码格式
- 默认编码格式 : urlencoded
- 如果要上传文件需要使用 Formdata 对象
- 数据格式 : username=shawn&password=1111
- 提交位置 : django后端会自动帮你解析封装到request.POST中, 文件提交到
request.FILES
中
5.json.loads( )是否可以转Bytes格式
- 3.5之前不行, 需要我们手动将 Bytes 格式转成 str 类型, 然后再进行转换
- 3.6以后可以, Bytes无需手动转 str 类型, 它内部会自动帮你转成 str, 再转成 json
- 查看
json.loads( )
的源码可以得到验证 :
三:Ajax文件上传
1.HTTP请求中,body体中存放文件内容,ajax的本质就是发送HTTP请求,所以 它可以上传文件
2.上传文件的方式有2种:① form表单,② ajax
固定模板
var formdata=new FormData()
formdata.append('myfile',$("#id_file")[0].files[0])
// 还可以带数据
$.ajax({
url:'/uploadfile/',
method: 'post',
//上传文件必须写这两句话
processData:false, # 预处理数据,
contentType:false, # 不指定编码,如果不写contentType,默认用urlencoded
data:formdata, # formdata内部指定了编码,并且自行处理数据
success:function (data) {
console.log(data)
}
})
基于ajax上传文件
aja_files.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="/static/bootstrap/css/bootstrap.css">
<script src="/static/js/jquery-3.5.1.min.js"></script>
</head>
<body>
<div class="container-fluid">
<div class="row">
<div class="col-md-6 col-lg-offset-3" style="margin-top: 100px;">
<h2>通过ajax上传</h2><br>
<input type="file" name="myfile" id="file1"><br>
<button id="btn" class="btn btn-success">上传</button>
</div>
</div>
</div>
<script>
$('#btn').click(function () {
var formdata = new FormData()
formdata.append('myfile', $('#file1')[0].files[0])
$.ajax({
url: '/upload/',
method: 'post',
processData: false,
contentType: false,
data: formdata,
success: function (data) {
alert(data)
},
error: function () {
console.log('出错了')
}
})
})
</script>
</body>
</html>
views.py
from django.shortcuts import render, HttpResponse
def ajax_files(request):
return render(request, 'aja_files.html')
#1、简单的视图函数。
def upload(request):
file = request.FILES.get('myfile')
with open(file.name, 'wb') as f:
for line in file:
f.write(line)
return HttpResponse('上传成功')
#2、 或者下面的视图函数也行
def ajax_file(request):
if request.is_ajax():
remark = request.POST.get('remark')
myfile = request.FILES.get('myfile')
print(remark) # haha
print(myfile) # 1.jpg
print(type(myfile)) # <class 'django.core.files.uploadedfile.InMemoryUploadedFile'>
with open(myfile.name,'wb')as f:
for line in myfile:
f.write(line)
return HttpResponse('使用ajax文件上传成功')
return render(request, 'aja_files.html')
urls.py
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^ajax_file/', views.index),
url(r'^upload/', views.upload),
#url(r'^upload/', views.ajax_file),
]
基于form表单上传文件
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="/static/bootstrap/css/bootstrap.css">
</head>
<body>
<div class="container-fluid">
<div class="row">
<div class="col-md-6" style="margin-top: 10px;">
<h2>通过form表单上传文件</h2><br>
<form action="/upload/" method="post" enctype="multipart/form-data">
{# 上传文件使用multipart/form-data编码类型 #}
<input type="file" name="myfile"><br>
<input type="submit" value="提交" class="btn btn-success">
</form>
</div>
</div>
</div>
</body>
</html>
views.py
from django.shortcuts import render, HttpResponse
def index(request):
return render(request, 'index.html')
def upload(request):
file = request.FILES.get('myfile')
with open(file.name, 'wb') as f:
for line in file:
f.write(line)
return HttpResponse('上传成功')
# 改写
def file_upload(request):
if request.method=='GET':
return render(request,'file_upload.html')
else:
name=request.POST.get('name')
myfile=request.FILES.get('myfile')
print(type(myfile)) # 查看类型
from django.core.files.uploadedfile import InMemoryUploadedFile
with open(myfile.name,'wb') as f:
for line in myfile:
f.write(line)
return HttpResponse('上传成功')
urls.py
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url('^index/', views.index),
url('^upload/', views.upload),
]
form表单上传文件版本二:
file_upload.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>上传文件</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
<h1>form表单上传文件</h1>
<form action="" method="post" enctype="multipart/form-data"> {# 上传文件使用multipart/form-data编码类型 #}
<p>用户名:<input type="text" name="name"></p>
<p>文件:<input type="file" name="myfile"></p>
<input type="submit" value="提交">
</form>
</body>
</html>
views.py
from django.shortcuts import render, HttpResponse, redirect
from django.http import JsonResponse
# Create your views here.
from app01 import models
def file_upload(request):
if request.method == 'GET':
return render(request, 'file_upload.html')
else:
name = request.POST.get('name')
myfile = request.FILES.get('myfile')
print(type(myfile)) # 查看类型
from django.core.files.uploadedfile import InMemoryUploadedFile
with open(myfile.name, 'wb') as f:
for line in myfile:
f.write(line)
return HttpResponse('上传成功')
urls.py
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^file_upload/', views.file_upload),
]
四:Ajax提交JSON格式
固定格式 - 简
$.ajax({
url:'/uploadjson/',
method:'post',
contentType: 'application/json',
data:JSON.stringify({name:$("#id_name1").val(),password:$("#id_password1").val()}),
success: function (data) {
// 成功,会触发这个
},
error: function () {
// 失败,会触发这个
}
})
固定格式 - 繁
$.ajax({
url:'/uploadjson/', //写全,是什么样就写什么样
method:'post',
contentType: 'application/json',
//data要是json格式字符串
//data:'{"name":"","password":""}',
//把字典转成json格式字符串
//JSON.stringify(dic)
//把json格式字符串转成对象
//JSON.parse(data)
data:JSON.stringify({name:$("#id_name1").val(),password:$("#id_password1").val()}),
success:function (data) {
//返回字符串类型,需要转成js的对象,字典
//1 如果:django 返回的是HttpResponse,data是json格式字符串,需要自行转成字典
//2 如果:django 返回的是JsonResponse,data是就是字典
//ajax这个方法做的是,如果响应数据是json格式,自动反序列化
console.log(typeof data)
var res=JSON.parse(data)
console.log(typeof res)
console.log(res.status)
console.log(res.msg)
}
})
后端返回数据
- HttpResponse:没有指定响应编码,默认使用
text/html
- JsonResponse:指定关联相应编码:
application/json
- ajax方法:会进行判断,如果相应编码是
application/json
,就自动调用JSON.parser()
,如果不是json格式的数据,就不会处理
js中的json序列化和反序列化:
- 序列化:
JSON.stringfy(data)
- 反序列化:
JSON.parser()
五:Django内置序列化器
1.在django中,把JS对象(字典)转成JSON格式,
json.dumps
实现不了,2.但是,Django内置了一个东西,可以把对象转换成JSON格式,这个东西,就是:
序列化器
伪代码
from bms_book.models import Book
from django.core import serializers
book_list = Book.objects.all()
res = serializers.serialize("json", book_list)
print(res)
内部原理
ll=[]
for book in book_list:
ll.append({'name':book.name,'price':book.price, 'date':book.publish_date, 'publisher': book.publisher, 'authors': book.authors})
import json
res=json.dumps(ll)
实例
import os
if __name__ == '__main__':
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BookManagementSystem_v1.settings")
import django
django.setup()
from bms_book.models import Book
from django.core import serializers
book_list = Book.objects.all()
res = serializers.serialize("json", book_list)
print(res)
分页器
练习
1.登录校验
(使用ajax实现)用户在表单输入用户名与密码,通过Ajax提交给服务器,服务器验证后返回响应信息,客户端通过响应信息确定是否登录成功,成功,则跳转到首页,否则,在页面上显示相应的错误信息
login.html
<div class="input-group">
<span class="input-group-addon">
<i class="fa fa-user" aria-hidden="true"></i>
</span>
<input type="text" class="form-control" id="usr" name="username" placeholder="请输入用户名" required>
</div>
<div class="input-group">
<span class="input-group-addon">
<i class="fa fa-unlock-alt" aria-hidden="true"></i>
</span>
<input type="password" class="form-control" id="pwd" name="password" placeholder="请输入密码" required>
</div>
<div class="form-group">
<button type="submit" class="btn btn-success btn-block" id="btn-login">登录</button>
</div>
views.py
def login(request):
if request.method == "POST":
username = request.POST.get('username')
password = request.POST.get('password')
if not username:
return JsonResponse({'code': 3, 'info': '请填写用户名!'})
elif not password:
return JsonResponse({'code': 3, 'info': '请填写密码!'})
try:
user = models.UserInfo.objects.get(username=username)
if user:
if user.password == password:
request.session["login_user"] = username
return JsonResponse({'code': 1, 'info': '登录成功!'})
else:
return JsonResponse({'code': 2, 'info': '密码错误!'})
else:
return JsonResponse({'code': 4, 'info': '该账号不存在!'})
except:
return JsonResponse({'code': 4, 'info': '该账号不存在!'})
return render(request, "general/Login.html")
2.文件上传的2种方式
使用ajax和form表单两种方式上传文件,保存到项目跟路径下的media文件加
〇 media文件夹添加设置
- settings.py中添加
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, "media").replace("\\", "/")
- 在项目根目录下创建
media
文件夹,再创建二级文件夹`upload_files,用于存放上传的文件
① form表单上传文件
upload.html
<form action="{% url 'upload' %}" method="post" enctype="multipart/form-data">
<input type="file" name="my_file"><br>
<button type="submit" class="btn btn-success">上传</button>
</form>
views.py
def upload(request):
import os
if request.method == 'POST':
file = request.FILES.get('my_file')
if file:
from BookManagementSystem_v1 import settings
path = os.path.join(settings.MEDIA_ROOT, "upload_files", file.name)
with open(path, 'wb') as f:
for line in file.chunks():
f.write(line)
return HttpResponse('文件上传成功!')
else:
return HttpResponse('请选择文件')
return render(request, 'general/Upload.html')
② ajax上传文件
upload.html
<div class="col-md-3">
<div class="panel panel-default">
<div class="panel-heading">
<ol class="breadcrumb margin-bottom-0">
当前位置:
<li class="active">文件上传</li>
</ol>
</div>
<div class="panel-body max-height-800">
<div class="col-md-4">
<br>
<input type="file" id="my_file"><br>
<button type="submit" class="btn btn-success" id="btn-upload">上传</button>
<br>
</div>
</div>
</div>
</div>
<div class="col-md-2">
<div class="alert alert-success alert-dismissible" role="alert" id="my-info"
style="display: none">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<strong></strong>
</div>
</div>
<script>
$('#btn-upload').click(function () {
var formData = new FormData()
formData.append('my_file', $("#my_file")[0].files[0])
$.ajax({
url: '{% url 'upload_backend' %}',
method: 'post',
processData: false,
contentType: false,
data: formData,
success: function (data) {
if (data.code == 1) {
$('#my-info').css('display', 'block')
$('#my-info').removeClass('alert-danger').addClass('alert-success')
$('#my-info strong').text(data.info)
} else {
$('#my-info').css('display', 'block')
$('#my-info').removeClass('alert-success').addClass('alert-danger')
$('#my-info strong').text(data.info)
}
},
error: function () {
$('#my-info').css('display', 'block')
$('#my-info').removeClass('alert-success').addClass('alert-danger')
$('#my-info strong').text('系统出错了!')
}
})
})
</script>
views.py
def upload(request):
return render(request, 'general/Upload.html')
def upload_backend(request):
import os
file = request.FILES.get('my_file')
print(file)
print(type(file))
if file:
from BookManagementSystem_v1 import settings
path = os.path.join(settings.MEDIA_ROOT, "upload_img", file.name)
with open(path, 'wb') as f:
for line in file.chunks():
f.write(line)
print('文件上传成功!')
return JsonResponse({'code': 1, 'info': '文件上传成功!'})
else:
print('请选择文件!')
return JsonResponse({'code': 2, 'info': '请选择文件!'})
3.使用ajax提交json格式数据
前端用ajax获取标签内数据,并转换成json格式的字符串对象,提交到后端后,对象转换成json格式,返回给前端
upload_json.html
<div class="col-md-3">
<div class="panel panel-default">
<div class="panel-heading">
<ol class="breadcrumb margin-bottom-0">
当前位置:
<li class="active">JSON上传数据</li>
</ol>
</div>
<div class="panel-body max-height-800">
<div class="col-md-10 col-md-offset-1">
<br>
<input type="text" id="usr" class="form-control" placeholder="请输入昵称"><br>
<input type="text" id="msg" class="form-control" placeholder="请输入留言内容"><br>
<button class="btn btn-success btn-block" id="btn-upload">上传</button>
<br>
</div>
</div>
</div>
</div>
<div class="col-md-2">
<div class="alert alert-success alert-dismissible" role="alert" id="my-info"
style="display: none">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<strong></strong>
<p></p>
</div>
</div>
<script>
$('#btn-upload').click(function () {
$.ajax({
url: '{% url 'upload_json_backend' %}',
method: 'post',
contentType: 'application/json',
data: JSON.stringify({name: $("#usr").val(), message: $("#msg").val()}),
success: function (data) {
$('#my-info').css('display', 'block')
$('#my-info').removeClass('alert-danger').addClass('alert-success')
$('#my-info strong').text(data.msg)
$('#my-info p').text(data.info)
},
error: function () {
$('#my-info').css('display', 'block')
$('#my-info').removeClass('alert-success').addClass('alert-danger')
$('#my-info strong').text('系统出错了!')
}
})
})
</script>
views.py
import json
def upload_json_backend(request):
data = request.body
data1 = json.loads(data.decode('utf-8'))
ret = f'用户:{data1["name"]} 发表了留言:{data1["message"]}'
dic = {'msg': '成功', 'info': ret}
return JsonResponse(dic)
4.实现简单的注册功能
实现简单的注册功能,当光标移除用户名的输入框,去后端校验,如果用户名存在,提示错误,并且把输入框中的文字清除
5.django处理XSS攻击的底层原理
把标签中的特殊字符进行替换
总结1:
1 ajax发送其他请求
1 大坑
-如果在form表单中,写button和input是submit类型,会触发form表单的提交
-如果不想触发:
-不写在form表单中
-使用input,类型是button
2 坑
-后端响应格式如果是:html/text格式,ajax接收到数据后需要自己转成对象
-后端响应格式是:json,ajax接收到数据后会自动转成对象
-总结:后端返回数据,统一都用JsonResponse、
3 坑
-如果使用了ajax,后端就不要返回rediret,render,HttpResponse
-直接返回JsonResponse
1.1 登录功能前端
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
</head>
<body>
<p> 用户名:<input type="text" id="id_name"></p>
<p> 密码:<input type="password" id="id_password"></p>
<button id="id_btn">提交</button> <span class="error" style="color: red"></span>
</body>
<script>
$('#id_btn').click(function () {
$.ajax({
url: '/login/',
method: 'post',
data: {username: $('#id_name').val(), password: $('#id_password').val()},
success: function (data) {
//res=JSON.parse(data)
//console.log(data)
//console.log(res)
// data 现在是对象类型
if(data.status==100){
//登录成功,重定向到百度,前端重定向
location.href='http://www.baidu.com'
//location.href='/index/'
}else {
//登录失败
//$('.error').html(data.msg).css({'color':'red'})
$('.error').html(data.msg)
}
},
error: function (data) {
console.log(data)
}
})
})
</script>
</html>
1.2 登录功能后端
from django.shortcuts import render,redirect,HttpResponse
from django.http import JsonResponse
# Create your views here.
from app01 import models
import json
def login(request):
if request.method=='GET':
return render(request,'login.html')
# elif request.method=='POST':
elif request.is_ajax():
response={'status':100,'msg':None}
name=request.POST.get('username')
password=request.POST.get('password')
user=models.User.objects.filter(name=name,password=password).first()
if user:
# 用户名和密码都对了
# return redirect('') 出错
response['msg']="登录成功"
else:
response['status']=101
response['msg'] = "用户名或密码错误"
# return HttpResponse(json.dumps(response))
return JsonResponse(response)
# return redirect('http://www.baidu.com')
# return render(request,'login.html')
1.3 登录功能路由
url(r'^login/', views.login),
1.4 登录功能模型类
from django.db import models
# Create your models here.
class User(models.Model):
name=models.CharField(max_length=32)
password=models.CharField(max_length=32)
2 上传文件(ajax和form两种方式)
1 http --post--请求,有编码格式,主流有三种
-urlencoded :默认的----》从request.POST取提交的数据
-form-data :上传文件的----》从request.POST取提交的数据,request.FILES中取文件
-json :ajax发送json格式数据-----》request.POST取不出数据了
2 使用ajax和form表单,默认都是urlencoded格式
3 如果上传文件:form表单指定格式,ajax要使用Formdata对象
4 如果编码方式是urlencoded格式,放到body体中数据格式如下
username=lqz&password=123
5 如果是formdata编码格式,body体中是:两部分,数据和文件
6 如果是json格式,body体中的格式是:就是json格式字符串
-注意:注意:注意:如果这种格式,request.POST取不到值了
2.1 form表单上传文件
<h1>form表单上传文件</h1>
<form action="" method="post" enctype="multipart/form-data">
<p>用户名:<input type="text" name="name"></p>
<p>文件:<input type="file" name="myfile"></p>
<input type="submit" value="提交">
</form>
2.2 ajax 上传文件
<h1>ajax上传文件</h1>
<p>用户名:<input type="text" id="id_name"></p>
<p>文件:<input type="file" id="id_myfile"></p>
<button id="id_btn">提交</button>
<script>
$('#id_btn').click(function () {
//如果要上传文件,需要借助于一个js的FormData对象
var formdata = new FormData() //实例化得到一个FormData对象
formdata.append('name', $('#id_name').val()) //追加了一个name对应填入的值
//能追加文件
var file = $('#id_myfile')[0].files[0]
formdata.append('myfile', file)
$.ajax({
url: 'file_upload',
method: 'post',
//上传文件,一定要注意如下两行
processData: false, //不预处理数据,
contentType: false, //不指定编码格式,使用formdata对象的默认编码就是formdata格式
data: formdata,
success: function (data) {
console.log(data)
}
})
})
</script>
2.3 后端
def file_upload(request):
if request.method=='GET':
return render(request,'file_upload.html')
else:
name=request.POST.get('name')
myfile=request.FILES.get('myfile')
print(type(myfile)) # 查看类型
from django.core.files.uploadedfile import InMemoryUploadedFile
with open(myfile.name,'wb') as f:
for line in myfile:
f.write(line)
return HttpResponse('上传成功')
2.4 路由
url(r'^file_upload/', views.file_upload),
3 ajax上传json格式
3.1 前端
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
</head>
<body>
<h1>ajax提交json格式</h1>
<p>用户名: <input type="text" id="id_name"></p>
<p>密码: <input type="password" id="id_password"></p>
<button id="id_button">提交</button>
</body>
<script>
$('#id_button').click(function () {
$.ajax({
url: '/ajax_json/',
method: 'post',
contentType: 'application/json', //指定编码格式
data: JSON.stringify({name:$('#id_name').val(),password:$('#id_password').val()}), //json格式字符串
success: function (data) {
console.log(data)
}
})
})
</script>
</html>
3.2 后端
def ajax_json(request):
if request.method=='GET':
return render(request,'ajax_json.html')
else:
# json格式,从POST中取不出来
name=request.POST.get('name')
print(type(request.POST))
# from django.http.request import QueryDict
print(name)
# 在body体中,b格式
request.data=json.loads(request.body)
name=request.data.get('name')
password=request.data.get('password')
print(name)
print(password)
return HttpResponse('ok')
4 django内置序列化(了解)
把对象转成json格式字符串,django内置的不好用,字段不能控制
目前阶段,要做序列化,for循环拼列表套字典
4.1 后端
def test(request):
user_list = models.User.objects.all()
ret = serializers.serialize("json", user_list)
return HttpResponse(ret)
4.2 路由
url(r'^test/', views.test),
5 分页器的使用
##############分页器
###批量插入数据
# def books_page(request):
# # 第一种方案,每循环依次,操作一下数据库,性能低
# # for i in range(1000):
# # book=models.Books.objects.create(name='图书%s'%i,price=i+10,publish='东京出版社')
# #
# # 第二种方案,批量插入
# book_list=[]
# for i in range(1000):
# book=models.Books(name='图书%s'%i,price=i+10,publish='东京出版社')
# book_list.append(book)
#
# models.Books.objects.bulk_create(book_list,batch_size=100)
#
#
# return HttpResponse('ok')
from django.core.paginator import Paginator
def books_page(request):
book_list=models.Books.objects.all()
paginator=Paginator(book_list,10)
# Paginator对象的属性
print(paginator.count) # 数据总条数
print(paginator.num_pages) # 总页数
print(paginator.per_page) # 每页显示条数
print(paginator.page_range) # range(1, 101)
print(paginator.page(1))
# Page对象的属性和方法
# has_next 是否有下一页
# next_page_number 下一页页码
# has_previous 是否有上一页
# previous_page_number 上一页页码
# object_list 分页之后的数据列表
# number 当前页
page=paginator.page(2)
print(page.has_next())
print(page.next_page_number())
print(page.has_previous())
print(page.previous_page_number())
print(page.object_list)
print(page.number)
return render(request,'book_page.html',locals())
练习
1 使用ajax发送post请求,完成注册功能,注册成功,跳转到登陆,登陆成功跳转到百度
2 使用ajax上传文件,保存到项目路径的media路径下(登录成功才能上传文件)
3 使用ajax上传json格式数据,写一个装饰器,实现不论前端以什么格式传递数据,我从视图函数中都从request.data中取值(POST的数据)
补充
json.loads(b'dfdasfda')
问题:json可以直接loads bytes格式吗?
-3.5之前不可以
-3.6以后可以