一:前后端传输数据的编码格式(contentType)
1.研究post请求数据的编码格式
# get请求数据的编码格式
get请求数据就是直接放在url后面的
url?username=jason&password=123
2.可以朝后端发送post请求的方式
1.form表单
2.Ajax请求
3.前后端传输数据的编码格式
urlencoded
formdata
json
![image](https://img2022.cnblogs.com/blog/2608805/202203/2608805-20220306224041993-986949868.png)
form表单默认的数据编码格式是Content-Type: urlencoded
数据格式: username=123&password=123
![image](https://img2022.cnblogs.com/blog/2608805/202203/2608805-20220306224048224-1757950499.png)
1.django后端针对符合urlencoded编码格式的数据都会自动帮你解析封装request.POST中。
username=jason&password=123 >>> request.POST
2.如果你把编码格式改成formdata,那么针对普通的键值对还是解析到request.POST中而将文件解析到request.FILES中
总结:
1.针对不同的编码格式,Django在后端内自动解析,然后放在不同的方法里面去,让用户非常简单快捷的就能够来操作,WSGI只是做了初步的封装,Django做了二次封装,主要是Django做的。
2.form表单是没有办法发送json格式数据的
<form action="" method="post" enctype="multipart/form-data"> {# 修改编码格式为form-data #}
<p>username: <input type="text" name="username" class="form-control"></p>
<p>password: <input type="password" name="password" class="form-control"></p>
<p>file: <input type="file" name="file"></p>
<input type="submit" class="btn btn-success">
</form>
![image](https://img2022.cnblogs.com/blog/2608805/202203/2608805-20220306224056737-482213961.png)
6.研究Ajax默认编码格式
默认的编码格式也是urlencoded
![image](https://img2022.cnblogs.com/blog/2608805/202203/2608805-20220306224102950-1507306206.png)
数据格式:username=jason&age=20
![image](https://img2022.cnblogs.com/blog/2608805/202203/2608805-20220306224109619-889446311.png)
django后端针对符合urlencoded编码格式的数据都会自动帮你解析封装到request.POST中
username=jason&age=20 >>> request.POST
二:ajax发送json格式数据
1.Ajax发送json格式数据
前后端传输数据的时候一定要确保"编码格式"跟数据真正的格式是一致的!
2.编码格式转换成JSON格式
![image](https://img2022.cnblogs.com/blog/2608805/202203/2608805-20220306224115899-1532724026.png)
3.发送数据必须与编码格式保持一致
![image](https://img2022.cnblogs.com/blog/2608805/202203/2608805-20220306224120996-488435836.png)
4.django后端不会帮你处理json格式数据需要手动处理
1.django针对json格式的数据 不会做任何的处理
解决方法:
Django后端不会帮你处理json格式数据需要自己手动去request.body获取并处理!
![image](https://img2022.cnblogs.com/blog/2608805/202203/2608805-20220306224126402-15504338.png)
5.后端手动处理json格式数据
以下有两种获取json格式数据方法:
1.第一种操作比较繁琐,但语句明显
2.第二种操作比较简洁,但对小白来说比较复杂
request对象方法补充
request.is_ajax()
判断当前请求是否是ajax请求 返回布尔值
import json
def ab_json(request):
# 判判断当前请求是否是ajax请求 返回布尔值
if request.is_ajax():
# 获取二进制格式字符串
print(request.body) # {"username":"jason","age":25}
# 获取json格式数据方式1:
# 针对json格式数据需要你自己手动处理
# 1.接收json二进制格式字符串数据
json_bytes = request.body
# 2.将二进制数据解码
json_str = json_bytes.decode('utf-8')
# 3.将json格式数据反序列化
json_dict = json.loads(json_str)
print(json_dict, type(json_dict))
# {'username': 'jason', 'age': 25} <class 'dict'>
# 获取json格式数据方式2:
以下方法简便为一行
# 1.json.loads括号内如果传入了一个二进制格式的数据那么内部自动解码再反序列化
# 针对json格式数据需要你自己手动处理
# 1.接收json二进制格式字符串数据
json_bytes = request.body
# 2.将二进制格式数据自动解码再反序列化
json_dict = json.loads(json_bytes)
print(json_dict, type(json_dict))
return render(request, 'ab_json.html')
<button class="btn btn-danger" id="d1">点我</button>
<script>
// 点击事件
$('#d1').click(function () {
$.ajax({
url: '',
type: 'post',
// 发送数据需要与编码格式一致 将数据转换成JSON格式数据
data: JSON.stringify({'username':'jason','age':25}),
// 指定编码格式 将urlencoded改为json编码格式
contentType: 'application/json',
success:function () {
}
})
})
</script>
![image](https://img2022.cnblogs.com/blog/2608805/202203/2608805-20220306224135823-472082488.png)
6.ajax发送json格式数据需要注意点
1.contentType参数指定成:application/json
2.数据是真正的json格式数据
3.django后端不会帮你处理json格式数据需要你自己去request.body获取并处理
三:ajax发送文件
1.Ajax发送文件关键字
Ajax发送文件需要借助于js内置对象FormData
2.Ajax发送文件操作
<p>username: <input type="text" id="d1"> </p>
<p>password: <input type="text" id="d2"> </p>
<p><input type="file" id="d3"> </p>
<button class="btn btn-info" id="d4"></button>
<script>
// 点击按钮朝后端发送普通键值对和文件数据
$('#d4').on('click', function () {
// 1.需要先利用FormData内置对象
let formDateObj = new FormData();
// 2.添加普通的键值对
formDateObj.append('username', $('#d1').val());
formDateObj.append('password', $('#d2').val());
// 3.添加文件对象
formDateObj.append('myfile', $('#d3')[0].files[0])
// 4.将对象基于ajax发送给后端
$.ajax({
url:'',
type:'post',
data:formDateObj, // 直接将对象放在data后面即可
// ajax发送文件必须要指定的两个参数
contentType:false, // 告诉浏览器不需使用任何编码 django后端能够自动识别formdata对象
processData:false, // 告诉你的浏览器不要对你的数据进行任何处理
// 朝后端发送数据
success:function (args) {
}
})
})
</script>
def ab_file(request):
# 判断是否为Ajax请求 返回布尔值
if request.is_ajax():
# 判断是否为POST请求
if request.method == 'POST':
# 获取对应的数据
print(request.POST)
print(request.FILES)
return render(request, 'ab_file.html')
![image](https://img2022.cnblogs.com/blog/2608805/202203/2608805-20220306224144650-825782110.png)
3.总结Ajax发送文件
1.需要利用内置对象FormData (普通键值对和文件都可以发送)
// 2 添加普通的键值对
formDateObj.append('username',$('#d1').val());
formDateObj.append('password',$('#d2').val());
// 3 添加文件对象
formDateObj.append('myfile',$('#d3')[0].files[0])
2.需要指定两个关键性的参数
contentType:false, // 不需使用任何编码 django后端能够自动识别formdata对象
processData:false, // 告诉你的浏览器不要对你的数据进行任何处理
3.django后端能够直接识别到formdata对象并且能够将内部的普通键值自动解析并封装到request.POST中 文件数据自动解析并封装到request.FILES中
四:django自带的序列化组件(drf做铺垫)
如果发现你可以直接使用MySQL但是无法使用sqlite3
不要慌张不要恐惧 你只需要按照之前MySQL的操作将sqlite3的驱动装一下即可
1.创建表数据
from django.db import models
class User(models.Model):
username = models.CharField(max_length=32,verbose_name='用户名')
age = models.IntegerField(verbose_name='年龄')
gender_choices = (
(1, 'male'),
(2, 'female'),
(3, 'others'),
)
gender = models.IntegerField(choices=gender_choices, verbose_name='性别')
![image](https://img2022.cnblogs.com/blog/2608805/202203/2608805-20220306224153573-1973919703.png)
2.案例:需求:
在前端给我获取到后端用户表里面所有的数据 并且要是列表套字典
1.前后端分离就无法使用"模板语法"
2.可以是json进行前后端交互
将后端数据构造成"列表套字典"
from django.http import JsonResponse
def ab_ser(request):
user_queryset = models.User.objects.all()
# [{},{},{},{},{}]
# 将数据构造成列表套字典
user_list = []
for user_obj in user_queryset:
# tmp产生一个字典,字典内封装一些数据
tmp = {
'pk': user_obj.pk,
'username': user_obj.username,
'age': user_obj.age,
'gender': user_obj.get_gender_display()
}
# 将字典添加到列表内
user_list.append(tmp)
# 将列表套字典到页面
return JsonResponse(user_list, safe=False)
{# for循环user_queryset内数据 #}
{% for user_obj in user_queryset %}
<p>{{ user_obj }}</p>
{% endfor %}
![image](https://img2022.cnblogs.com/blog/2608805/202203/2608805-20220306224200577-885312714.png)
3.JSON序列化前后端分离项目总结
1.返回的数据是一个列表套字典的格式
[
{"pk": 1, "username": "jason", "age": 25, "gender": "male"},
{"pk": 2, "username": "egon", "age": 31, "gender": "female"},
{"pk": 3, "username": "kevin", "age": 32, "gender": "others"},
{"pk": 4, "username": "tank", "age": 40, "gender": 4}
]
前后端分离的项目
1.作为后端开发的你只需要写代码将数据处理好
2.能够序列化返回给前端即可
3.再写一个接口文档 告诉前端每个字段代表的意思即可,
4.至于后面数据怎么渲染都不管你的事,后端只需要返回即可,
5.这就叫写接口 前后端分离
4.serializers前后端分离
# 导入serializers 序列化模块前后端分离
from django.core import serializers
def ab_ser(request):
user_queryset = models.User.objects.all()
# 序列化 # 第一个参数序列化成什么格式 第二个参数序列化的数据
res = serializers.serialize('json', user_queryset)
"""serializers会自动帮你将数据变成json格式的字符串 并且内部非常的全面"""
return HttpResponse(res)
![image](https://img2022.cnblogs.com/blog/2608805/202203/2608805-20220306224207025-428847235.png)
5.serializers序列化前后端分离项目总结
1.serializers序列化后数据来自于那张表 主键 序号等都会显示,更加明确!
[
{ "model": "app01.user",
"pk": 1,
"fields": {"username": "jason", "age": 25, "gender": 1}},
{ "model": "app01.user",
"pk": 2,
"fields": {"username": "egon", "age": 31, "gender": 2}},
{ "model": "app01.user",
"pk": 3,
"fields": {"username": "kevin", "age": 32, "gender": 3}},
{" model": "app01.user",
"pk": 4,
"fields": {"username": "tank", "age": 40, "gender": 4}}
]
2.写接口就是利用序列化组件渲染数据然后写一个接口文档 该交代交代一下就完事了
五:ajax结合sweetalert
1.两种方法刷新当前页面
// 1.lowb版本 直接刷新当前页面
{#window.location.reload() // 重新加载页面#}
// 缺点 当页面在分页的情况下,你在99页删除,刷新自动跳到第一页
// 2.利用DOM操作 动态刷新
currentBtn.parent().parent().remove() // 页面不刷新
2.搭建二次确认前提
- 导入dist文件与bootstrap.sweetalert文件
![image-20220303170015472]()
# 1.settings配置文件设置 静态配置
STATIC_URL = '/static/' # 接口前缀 令牌
STATICFILES_DIRS = [
# 将静态文件拼接到 顶级目录/暴露外界/环境变量
os.path.join(BASE_DIR, 'static')
]
# 2.user_list.html 动态引入静态文件
{# 动态引入静态文件 #}
{% load static %}
<link rel="stylesheet" href="{% static 'bootstrap-3.4.1-dist/css/sweetalert.css' %}">
<script src="{% static 'bootstrap-3.4.1-dist/js/sweetalert.min.js' %}"></script>
3.user_list
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--bootstrap引入 CSS CDN-->
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
<!--jQuery引入 CDN-->
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<!--Bootstrap引入 Js CDN-->
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
<style>
div.sweet-alert.showSweetAlert.visible h2{
padding-top: 10px;
}
</style>
{# 动态引入静态文件 #}
{% load static %}
<link rel="stylesheet" href="{% static 'bootstrap-3.4.1-dist/css/sweetalert.css' %}">
<script src="{% static 'bootstrap-3.4.1-dist/js/sweetalert.min.js' %}"></script>
</head>
<body>
{#左右不留白#}
<div class="container-fluid">
<h1 class="text-center">数据展示</h1>
{# 分12份#}
<div class="row">
<div class="col-md-8 col-md-offset-2">
<table class="table-striped table table-hover">
<thead>
<tr>
<th>ID</th>
<th>username</th>
<th>age</th>
<th>gender</th>
<th>actions</th>
</tr>
</thead>
<tbody>
{% for user_obj in user_queryset %}
<tr>
<td>{{ user_obj.pk }}</td>
<td>{{ user_obj.username }}</td>
<td>{{ user_obj.age }}</td>
{# 获取性别choices #}
<td>{{ user_obj.get_gender_display }}</td>
<td>
<button class="btn btn-primary btn-xs">编辑</button>
{# button 自定义标签属性 #}
<button class="btn btn-danger btn-xs del" delete_id="{{ user_obj.pk }}">删除</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
<script>
$('.del').on('click', function() {
// 先将当前标签对象存储起来
let currentBtn = $(this); // 指代当前被点击的对象
// 二次确认弹框
swal({
title: "请确定要删吗?",
text: "你可要考虑清楚",
type: "warning",
showCancelButton: true,
confirmButtonClass: "btn-danger",
confirmButtonText: "确认",
cancelButtonText: "拒绝",
closeOnConfirm: false,
closeOnCancel: false
},
function(isConfirm) {
// 判断用户是否真的要删除
if (isConfirm) {
// 朝后端发送ajax请求删除数据之后 再弹下面的提示框
$.ajax({
{#url: '/delete_user/' + currentBtn.attr('delete_id'), // 1 传递主键值方式1 #}
url: '/delete_user/', // 2 放在请求体里面
type: 'post',
data: {'delete_id':currentBtn.attr('delete_id')},
success:function (args) { // 回调函数 接受后端返回值 args = {'code':'','msg':''}
// 判断响应状态码 然后做不同的处理
if(args.code === 1000){
swal("删了", args.msg, "success");
// 两种方法刷新当前页面
// 1.lowb版本 直接刷新当前页面
{#window.location.reload() // 重新加载页面#}
// 缺点 当页面在分页的情况下,你在99页删除,刷新自动跳到第一页
// 2.利用DOM操作 动态刷新
currentBtn.parent().parent().remove() // 页面不刷新
}else{
swal('完了','出现了未知的错误', 'info')
}
}
})
swal("删除,确定", "删除成功", "success");
} else {
swal("在考虑一下","已撤销删除", "error");
}
});
})
</script>
</body>
</html>
4.user_list后端用户展示页面
def user_list(request):
user_queryset = models.User.objects.all()
return render(request, 'user_list.html', locals())
5.delete_user后端删除返回结果
from django.http import JsonResponse
def delete_user(request):
# 前后端在用ajax进行交互的时候 后端通常给ajax的回调函数返回一个字典格式的数据
# 判断是否为ajax请求 返回布尔值
if request.is_ajax():
# 判断是否为POST请求
if request.method == 'POST':
# code 响应状态码
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)
![image](https://img2022.cnblogs.com/blog/2608805/202203/2608805-20220306224335627-4325588.gif)
6.自定义二次确认增加延迟效果
$('.del').on('click', function() {
// 先将当前标签对象存储起来
let currentBtn = $(this); // 指代当前被点击的对象
// 二次确认弹框
swal({
title: "请确定要删吗?",
text: "你可要考虑清楚",
type: "warning",
showCancelButton: true,
confirmButtonClass: "btn-danger",
confirmButtonText: "确认",
cancelButtonText: "拒绝",
closeOnConfirm: false,
closeOnCancel: false,
showLoaderOnConfirm: true
},
showLoaderOnConfirm: true : 增加三点加载动态效果
7.delete_user
def delete_user(request):
# 前后端在用ajax进行交互的时候 后端通常给ajax的回调函数返回一个字典格式的数据
# 判断是否为ajax请求 返回布尔值
if request.is_ajax():
# 判断是否为POST请求
if request.method == 'POST':
# code 响应状态码
back_dic = {"code":1000,'msg':''}
# 模拟加载延迟效果
time.sleep(3) # 模拟操作数据的延迟
# 拿到当前用户想要删除的主键值
delete_id = request.POST.get('delete_id')
# 删除
models.User.objects.filter(pk=delete_id).delete()
back_dic['msg'] = '数据已经删除成功!'
# 我们需要告诉前端我们操作的结果
return JsonResponse(back_dic)
模拟加载延迟效果
time.sleep(3) # 模拟操作数据的延迟
![image](https://img2022.cnblogs.com/blog/2608805/202203/2608805-20220306224429840-1521109790.gif)