AJAX
JSON
JSON是JavaScript对象表示法(JavaScript Object Notation)。
JSON对象和字符串转换的两个方法:
- JSON.parse():用于JSON字符串转换成JavaScript对象(json只认双引号的字符串格式)
- JSON.stringify():用于将JavaScript值转换为JSON字符串。
choice参数
主要用于性别、学历、工作年限等应用场景,有利于节省资源。类似于MySQL约束中的enum。
# models.py
class User(models.Model):
username = models.CharField(max_length=32)
choices = [
(1, 'male'),
(2, 'female'),
(3, 'others'),
]
gender = models.IntegerField(choices=choices)
# test.py
user_obj = models.User.objects.filter(pk=1).first()
print(user_obj.username) # allen
print(user_obj.gender) # 注意:这里只显示编号1
# 要想获取对应的值,固定写法:数据对象.get_字段名_display()
print(user_obj.get_gender_display()) # male
MTV与MVC模型
Django称为MTV框架,本质上也是MVC框架
MTV:M(models);T(templates);V(views)
MVC:M(models);V(views);C(Controller)控制器相当于路由匹配
AJAX简介
AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步的Javascript和XML”,是一门js技术,原生js写代码繁杂,用jQuery实现ajax。
一大优点两大特性:
- 优点:不重新加载整个页面的情况下,与服务器交换数据并更新部分网页内容,不知不觉完成请求和响应过程。
- 异步提交
- 同步:提交任务后,原地等待任务的返回结果之后,再执行其他任务。
- 异步:提交任务后,不再原地等待,直接执行下一个任务,任务返回通过回调机制完成。
- 阻塞非阻塞:程序的运行状态(就绪、阻塞、运行)
- 局部刷新:页面不是整体刷新,而是页面某地方局部变化。
需求:展示前端页面,如何实现点击按钮发起请求在页面不刷新的情况下,完成数字的加法运算?
# 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'^add/', views.add),
]
# views.py
def add(request):
if request.is_ajax():
if request.method == 'POST':
d1 = request.POST.get('d1')
d2 = request.POST.get('d2')
res = int(d1) + int(d2)
return HttpResponse(res)
return render(request, 'add.html')
# add.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="/static/jQuery.js"></script>
{% load static %}
<script src="{% static 'bootstrap/js/bootstrap.min.js' %}"></script>
<link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}">
</head>
<body>
<input type="text" id="d1">+<input type="text" id="d2">=<input type="text" id="d3">
<p>
<button id="d4">点击计算</button>
</p>
<script>
$('#d4').on('click', function () {
//朝后端发数据
$.ajax({
url: '',//用于控制向后端提交数据的地址,默认当前地址
type: 'post',//制定ajax发送的请求方式
data: {'d1': $('#d1').val(), 'd2': $('#d2').val()},//发送的数据
success: function (data) {//异步提交任务,需通过回调函数来处理,data形参表示异步提交的返回结果
$('#d3').val(data) //通过DOM操作将内容渲染到标签内容上
}
})
})
</script>
</body>
</html>
效果如下:
前后端传输数据的编码格式
通过开发者工具F12查看contentTpye类型。
- form表单:默认提交数据编码格式是urlencoded
- urlencoded数据格式是
username=admin&password=123
,Django后端自动解析并打包给request.POST方法。 - formdata数据格式Django后端也会自动解析,但是数据放在request.FILES中。
- urlencoded数据格式是
- ajax:默认提交数据编码格式也是urlencoded
总结:Django后端针对不同的编码格式数据,会有不同的处理机制以及不同的获取数据方法。但是前后端做数据交互时,一定要明确所发数据的格式。
利用ajax发送json格式数据
由于前后端数据格式不一样,我们必须采取一种方式,使前后端数据交互的格式是一致的。
需求:展示前端页面,如何实现点击按钮发起请求在页面不刷新的情况下,完成json格式数据的加法运算?
# 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'^add/', views.add),
]
# views.py
from django.shortcuts import render, HttpResponse
import json
def add(request):
if request.is_ajax():
if request.method == 'POST':
print(request.body) # b'{"d1":"12","d2":"12"}'
json_bytes = request.body # 后端针对json数据不会自动解析,直接放到request.body中
json_str = str(json_bytes, encoding='utf-8')
dic = json.loads(json_str)
d1 = dic.get('d1')
d2 = dic.get('d2')
res = int(d1) + int(d2)
return HttpResponse(res)
return render(request, 'add.html')
# add.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="/static/jQuery.js"></script>
{% load static %}
<script src="{% static 'bootstrap/js/bootstrap.min.js' %}"></script>
<link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}">
</head>
<body>
<input type="text" id="d1">+<input type="text" id="d2">=<input type="text" id="d3">
<p>
<button id="d4">点击计算</button>
</p>
<script>
$('#d4').on('click', function () {
$.ajax({
url: '',
type: 'post',
contentType: 'application/json',//明确告诉后端当前的数据格式
data: JSON.stringify({'d1': $('#d1').val(), 'd2': $('#d2').val()}), //确保发送数据是json格式
success: function (data) {
$('#d3').val(data)
}
})
})
</script>
</body>
</html>
效果如下:
利用ajax发送文件格式数据
需求:如何实现利用ajax发送文件格式类型?
# 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'^add/', views.add),
]
# views.py
from django.shortcuts import render, HttpResponse
def add(request):
if request.is_ajax():
if request.method == 'POST':
print(request.POST)
print(request.FILES)
return HttpResponse('收到')
return render(request, 'add.html')
# add.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="/static/jQuery.js"></script>
{% load static %}
<script src="{% static 'bootstrap/js/bootstrap.min.js' %}"></script>
<link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}">
</head>
<body>
<p>用户名:<input type="text" name="username" id="d1"></p>
<p>密码:<input type="password" name="password" id="d2"></p>
<input type="file" name="myfile" id="d3">
<p>
<button id="d4">点击运行</button>
</p>
<script>
$('#d4').on('click', function () {
// 先生成一个formdata对象
var myformdata = new FormData();
// 向对象中添加普通键值
myformdata.append('username', $('#d1').val());
myformdata.append('password', $('#d2').val());
// 向对象中添加文件数据分为三步:
// 第一步:先通过jQuery查找该标签,$('#d3')拿到jQuery对象
// 第二步:将jQuery对象转换成原生js对象,$('#d3')[0]拿到原生js对象
// 第三步:利用原生js对象方法直接获取文件内容,$('#d3')[0].files返回列表
myformdata.append('myfile', $('#d3')[0].files[0]);
$.ajax({
url: '',
type: 'post',
data: myformdata,//直接放对象
contentType: false,//formdata对象自带编码
processData: false,//告知浏览器无需处理数据
success: function (data) {
alert(data)
}
})
})
</script>
</body>
</html>
效果如下:
ajax传文件注意事项:
- 利用formdata对象能够快速传输数据(键值对+文件)
- 参数设置data:formdata对象;contentType:false;processData:false
序列化组件
需求:将用户数据查询并返回前端,以列表套字典的形式,字典内数据是字段。
# models.py
from django.db import models
class User(models.Model):
username = models.CharField(max_length=32)
password = models.IntegerField(default=123)
choices = [
(1, 'male'),
(2, 'female'),
(3, 'others'),
]
gender = models.IntegerField(choices=choices)
# 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'^add/', views.add),
]
# views.py
from django.shortcuts import render, HttpResponse
from app01 import models
from django.core import serializers
def add(request):
user_obj = models.User.objects.all()
res = serializers.serialize('json', user_obj)
# 第一个参数是转换格式,第二个参数是queryset对象
return render(request, 'add.html', locals())
# add.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="/static/jQuery.js"></script>
{% load static %}
<script src="{% static 'bootstrap/js/bootstrap.min.js' %}"></script>
<link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}">
</head>
<body>
{{ res }} //返回列表套字典数据
</body>
</html>
效果如下:
AJAX+SweetAlert插件示例
示例地址:https://lipis.github.io/bootstrap-sweetalert/
# models.py
from django.db import models
class User(models.Model):
username = models.CharField(max_length=32)
password = models.IntegerField(default=123)
choices = [
(1, 'male'),
(2, 'female'),
(3, 'others'),
]
gender = models.IntegerField(choices=choices)
# 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'^add/', views.add),
]
# views.py
from django.shortcuts import render
from django.http import JsonResponse
from app01 import models
import time
def add(request):
# 使用ajax前后端交互,返回给前端字典
if request.method == 'POST':
time.sleep(2)
back_dic = {'code': 1000, 'msg': ''}
delete_id = request.POST.get('delete_id')
models.User.objects.filter(pk=delete_id).delete()
back_dic['msg'] = '真的被我删了'
return JsonResponse(back_dic)
queryset_user = models.User.objects.all()
return render(request, 'add.html', locals())
# add.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="/static/jQuery.js"></script>
{% load static %}
<script src="{% static 'bootstrap/js/bootstrap.min.js' %}"></script>
<script src="{% static 'dist/sweetalert.min.js' %}"></script>
<link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}">
<link rel="stylesheet" href="{% static 'dist/sweetalert.css' %}">
<style>
{#sweetalert不支持中文,修改样式#}
div.sweet-alert h2 {
padding-top: 10px;
}
</style>
</head>
<body>
<div class="container">
<div class="row">
<h2 class="text-center">数据展示</h2>
<table class="table table-hover table-bordered table-striped">
<thead>
<tr>
<th>序号</th>
<th>用户名</th>
<th>密码</th>
<th>性别</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for user_obj in queryset_user %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ user_obj.username }}</td>
<td>{{ user_obj.password }}</td>
<td>{{ user_obj.get_gender_display }}</td>
<td>
<a href="#" class="btn btn-primary btn-sm">编辑</a>
{#这里不能用id设置属性,因为在循环体内,并且a标签可以自定义属性#}
<a href="#" class="btn btn-danger btn-sm cancel" delete_id="{{ user_obj.pk }}">删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<script>
$('.cancel').click(function () {
var $btn = $(this); //this表示当前被点击对象
swal({
title: "确定删除?",
text: "删除后不能恢复",
type: "warning",
showCancelButton: true,//是否显示取消按钮
confirmButtonClass: "btn-danger",//确认按钮样式类
confirmButtonText: "老子就要删",//确认按钮文本
cancelButtonText: "惹不起",//取消按钮文本
showLoaderOnConfirm: true,//显示正在删除的动画效果
closeOnConfirm: false//点击确认按钮不关闭弹窗
},
function () {
$.ajax({
url: '',
type: 'post',
data: {'delete_id': $btn.attr('delete_id')}, //获取当前属性值,如果$btn.attr('delete_id',123)就是替换
success: function (data) {
if (data.code = 1000) {//自定义响应状态码
swal("data.msg", "你可以准备行李跑路吧!", "success");
//方式一:直接刷新页面
//window.location.reload()
//方式二:通过DOM操作实时删除
$btn.parent().parent().remove()
} else {
swal("发生未知错误", "我也不知道原因!", "info");
}
}
});
});
})
</script>
</body>
</html>