Ajax相关知识

目录

一.前后端传输数据的编码格式(contentType)

1.form表单

2.编码格式

3.Ajax

4.代码演示

后端

前端HTML

二.Ajax发送JSON格式数据

1.引入

后端

前端

2.后端

接收到的数据为空

解决办法

3.request方法判断Ajax

4.总结

前端在通过ajax请求发送数据的时候,一定要注参数修改

数据是真正的JSON格式数据

Django后端不会帮我们处理JSON格式数据,需要自己手动处理request.body中的数据

三.Ajax发送文件数据

1.Ajax发送文件数据需要借助js内置对象formdata

前端

后端

发送文件数据的格式

2.结论

Ajax发送文件数据需要利用内置对象FormData

需要指定两个关键性的参数

Django后端能直接自动识别到FormData对象

四.分页

1.前言

2.自定义分页器封装代码

3.后端使用方法

4.前端使用方法


一.前后端传输数据的编码格式(contentType)

主要研究POST请求数据的编码格式

因为GET请求数据就是直接放在url后面的

  • 可以朝后端发送post请求的方式
    • form请求
    • ajax请求

1.form表单

  • 前后端传输数据的格式
    • urlencoded
    • formdata
    • json

2.编码格式

  • form表单默认的编码格式是urlencoded
    • 通过查看请求头中的Content-Type参数
python 复制代码
text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding:gzip, deflate, br
Accept-Language:zh-CN,zh;q=0.9,en;q=0.8
Cache-Control:no-cache
Connection:keep-alive
Content-Length:27
Content-Type:application/x-www-form-urlencoded
  • 携带数据格式
python 复制代码
username=666666&password=66
  • Django后端针对urlencoded编码格式的数据会自动帮我们解析封装到request.POST中
  • 如果编码格式改为formdata,那么针对普通的键值对还是解析到request.POST中,而其他文件格式的数据解析到request.FILES中
  • form表单无法发送json格式数据

3.Ajax

python 复制代码
Accept:*/*
Accept-Encoding:gzip, deflate, br
Accept-Language:zh-CN,zh;q=0.9,en;q=0.8
Cache-Control:no-cache
Connection:keep-alive
Content-Length:31
Content-Type:application/x-www-form-urlencoded; charset=UTF-8
  • 默认的编码格式是urlencoded
  • 数据格式
python 复制代码
username=dream&password=1314521
  • Django后端针对urlencoded编码格式的数据会自动帮我们解析封装到request.POST中--->username = dream&password=123456

4.代码演示

后端

python 复制代码
def index(request):
    if request.method == 'POST':
        print(request.POST)
        print(request.FILES)
    return render(request, 'index.html')

前端HTML

python 复制代码
<form action="" method="post" enctype="multipart/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"></p>
    <p><input type="submit" class="btn btn-success"></p>
    <p><input type="button" class="btn btn-danger" value="按钮" id="d1"></p>
</form>

<script>
    $("#d1").click(function () {
        $.ajax({
            url: '',
            type: 'POST',
            data: {"username": "dream", "password": 1314521},
            success: function (args) {

            },
        })
    })
</script>

二.Ajax发送JSON格式数据

前后端传输数据的时候一定要保证编码格式数据与真正的数据格式是一致的

1.引入

后端

python 复制代码
def ab_json(request):
    if request.method == 'POST':
        print(request.POST) #<QueryDict: {}>
    return render(request, 'ab_json.html')

前端

python 复制代码
<button class="btn btn-danger" id="d1">点我</button>

<script>
    $('#d1').click(function () {
        $.ajax({
            url: '',
            type: 'post',
            // 前端数据转JSON格式数据 :JSON.stringify
            data: JSON.stringify({"username": "dream", "password": 521521}),
            // 不指定参数,默认就是 urlencoded
            contentType: 'application/json',
            success: function (args) {

            }
        })
    })
</script>
  • 请求标头携带的数据格式
    • 已成功转换为JSON格式
python 复制代码
{"username":"dream","password":521521}

2.后端

接收到的数据为空

python 复制代码
def ab_json(request):
    if request.method == 'POST':
        print(request.POST) #<QueryDict: {}>
    return render(request, 'ab_json.html')

Django 针对JSON格式的数据不会做任何处理

针对JSON格式的数据需要自己手动处理

解决办法

python 复制代码
def ab_json(request):
    print(request.is_ajax())  # True
    if request.method == 'POST':
        print(request.POST)  # <QueryDict: {}>

    print(request.body)  # 返回的是二进制数据 :b'{"username":"dream","password":521521}'
    # 针对JSON格式的数据需要自己手动处理
    json_bytes = request.body

    # (1)方式一:先解码 再转换数据格式
    json_str = json_bytes.decode('utf-8')
    json_dict = json.loads(json_str)
    print(json_dict, type(json_dict))  # {'username': 'dream', 'password': 521521} <class 'dict'>

    # (2)方式二:json.loads(二进制数据) 内部可以自动解码再反序列化
    json_dict_loads = json.loads(json_bytes)
    print(json_dict_loads, type(json_dict_loads))  # {'username': 'dream', 'password': 521521} <class 'dict'>


    return render(request, 'ab_json.html')

3.request方法判断Ajax

python 复制代码
request.is_ajax()

返回当前请求是否是ajax请求,返回布尔值

print(request.is_ajax()) 正常浏览器网址回车提交的是 GET 请求 - 结果是False 当我们发送ajax请求后 - 结果是True

4.总结

前端在通过ajax请求发送数据的时候,一定要注参数修改

python 复制代码
// 不指定参数,默认就是 urlencoded
contentType: 'application/json',

数据是真正的JSON格式数据

发送的数据一定要符合JSON格式

或经过JSON序列化再传输

Django后端不会帮我们处理JSON格式数据,需要自己手动处理request.body中的数据

通过Ajax传过来的数据是二进制数据

在request.body中要经过自己的反序列化才能拿到我们想要的数据

三.Ajax发送文件数据

1.Ajax发送文件数据需要借助js内置对象formdata

前端

python 复制代码
<p>username: <input type="text" name="username" id="d1"></p>
<p>password: <input type="password" name="password" id="d2"></p>
<p>file: <input type="file" id="d3"></p>

<button id="btn" class="btn btn-danger">提交</button>


<script>
    // 点击按钮向后端发送普通键值对数据和文件数据
    $("#btn").on('click', function () {
        // (1)先生成一个内置对象
        let formDataObj = new FormData();

        // (2)支持添加普通的键值对
        formDataObj.append('username', $("#d1").val());
        formDataObj.append('password', $("#d2").val());

        // (3)支持添加文件对象 ---> 先拿到标签对象 ----> 再拿到文件对象
        formDataObj.append('myfile', $("#d3")[0].files[0]);

        // (4)基于Ajax,将文件对象发送给后端
        $.ajax({
            url: '',
            type: 'post',
            // 直接将对象放到data里面即可
            data: formDataObj,

            // Ajax发送文件必须添加的两个参数
            // 不需要使用任何编码 -  Django后端能自动识别 formdata 对象
            contentType: false,
            // 告诉浏览器不要对我的数据进行任何处理
            processData: false,

            success: function (args) {

            }
        })
    })
</script>

后端

python 复制代码
def ab_file(request):
    if request.is_ajax():
        if request.method == 'POST':
            print('POST::>>', request.POST)
            # 普通键值对放在了  request.POST   中
            # POST::>> <QueryDict: {'username': ['dream'], 'password': ['666']}>
            print('FILES::>>', request.FILES)
            # 文件数据放在了  request.FILES   中
            # FILES::>> <MultiValueDict: {'myfile': [<InMemoryUploadedFile: img.png (image/png)>]}>

    return render(request, 'ab_file.html')

发送文件数据的格式

python 复制代码
// 点击按钮向后端发送普通键值对数据和文件数据
$("#btn").on('click', function () {
// (1)先生成一个内置对象
let formDataObj = new FormData();

// (2)支持添加普通的键值对
formDataObj.append('username', $("#d1").val());
formDataObj.append('password', $("#d2").val());

// (3)支持添加文件对象 ---> 先拿到标签对象 ----> 再拿到文件对象
formDataObj.append('myfile', $("#d3")[0].files[0]);

// (4)基于Ajax,将文件对象发送给后端
$.ajax({
url: '',
type: 'post',
// 直接将对象放到data里面即可
data: formDataObj,

// Ajax发送文件必须添加的两个参数
// 不需要使用任何编码 -  Django后端能自动识别 formdata 对象
contentType: false,
// 告诉浏览器不要对我的数据进行任何处理
processData: false,

success: function (args) {

}
})

2.结论

Ajax发送文件数据需要利用内置对象FormData

python 复制代码
// (1)先生成一个内置对象
let formDataObj = new FormData();

// (2)支持添加普通的键值对
formDataObj.append('username', $("#d1").val());
formDataObj.append('password', $("#d2").val());

// (3)支持添加文件对象 ---> 先拿到标签对象 ----> 再拿到文件对象
formDataObj.append('myfile', $("#d3")[0].files[0]);

需要指定两个关键性的参数

python 复制代码
// Ajax发送文件必须添加的两个参数
// 不需要使用任何编码 -  Django后端能自动识别 formdata 对象
contentType: false,
// 告诉浏览器不要对我的数据进行任何处理
processData: false,

Django后端能直接自动识别到FormData对象

  • 将内部的普通键值对自动解析并封装到request.POST中
  • 将内部的文件数据自动解析并封装到request.FILES中
python 复制代码
print('POST::>>', request.POST)
# 普通键值对放在了  request.POST   中
# POST::>> <QueryDict: {'username': ['dream'], 'password': ['666']}>

print('FILES::>>', request.FILES)
# 文件数据放在了  request.FILES   中
# FILES::>> <MultiValueDict: {'myfile': [<InMemoryUploadedFile: img.png (image/png)>]}>

四.分页

1.前言

当我们需要使用到非Django内置的第三方模块或者功能组件代码的时候,我们一般情况下会创建一个名为utils的文件夹,在该文件夹中对模块的功能进行划分

注意:样式基于bootstrap,需要引入bootstrap配置

2.自定义分页器封装代码

python 复制代码
class Pagination(object):
    def __init__(self, current_page, all_count, per_page_num=2, pager_count=11):
        """
        封装分页相关数据
        :param current_page: 当前页
        :param all_count:    数据库中的数据总条数
        :param per_page_num: 每页显示的数据条数
        :param pager_count:  最多显示的页码个数
        """
        try:
            current_page = int(current_page)
        except Exception as e:
            current_page = 1
 
        if current_page < 1:
            current_page = 1
 
        self.current_page = current_page
 
        self.all_count = all_count
        self.per_page_num = per_page_num
 
        # 总页码
        all_pager, tmp = divmod(all_count, per_page_num)
        if tmp:
            all_pager += 1
        self.all_pager = all_pager
 
        self.pager_count = pager_count
        self.pager_count_half = int((pager_count - 1) / 2)
 
    @property
    def start(self):
        return (self.current_page - 1) * self.per_page_num
 
    @property
    def end(self):
        return self.current_page * self.per_page_num
 
    def page_html(self):
        # 如果总页码 < 11个:
        if self.all_pager <= self.pager_count:
            pager_start = 1
            pager_end = self.all_pager + 1
        # 总页码  > 11
        else:
            # 当前页如果<=页面上最多显示11/2个页码
            if self.current_page <= self.pager_count_half:
                pager_start = 1
                pager_end = self.pager_count + 1
 
            # 当前页大于5
            else:
                # 页码翻到最后
                if (self.current_page + self.pager_count_half) > self.all_pager:
                    pager_end = self.all_pager + 1
                    pager_start = self.all_pager - self.pager_count + 1
                else:
                    pager_start = self.current_page - self.pager_count_half
                    pager_end = self.current_page + self.pager_count_half + 1
 
        page_html_list = []
        # 添加前面的nav和ul标签
        page_html_list.append('''
                    <nav aria-label='Page navigation>'
                    <ul class='pagination'>
                ''')
        first_page = '<li><a href="?page=%s">首页</a></li>' % (1)
        page_html_list.append(first_page)
 
        if self.current_page <= 1:
            prev_page = '<li class="disabled"><a href="#">上一页</a></li>'
        else:
            prev_page = '<li><a href="?page=%s">上一页</a></li>' % (self.current_page - 1,)
 
        page_html_list.append(prev_page)
 
        for i in range(pager_start, pager_end):
            if i == self.current_page:
                temp = '<li class="active"><a href="?page=%s">%s</a></li>' % (i, i,)
            else:
                temp = '<li><a href="?page=%s">%s</a></li>' % (i, i,)
            page_html_list.append(temp)
 
        if self.current_page >= self.all_pager:
            next_page = '<li class="disabled"><a href="#">下一页</a></li>'
        else:
            next_page = '<li><a href="?page=%s">下一页</a></li>' % (self.current_page + 1,)
        page_html_list.append(next_page)
 
        last_page = '<li><a href="?page=%s">尾页</a></li>' % (self.all_pager,)
        page_html_list.append(last_page)
        # 尾部添加标签
        page_html_list.append('''
                                           </nav>
                                           </ul>
                                       ''')
        return ''.join(page_html_list)

3.后端使用方法

python 复制代码
 def get_book(request):
   book_list = models.Book.objects.all()
   current_page = request.GET.get("page",1)
   all_count = book_list.count()
   page_obj = Pagination(current_page=current_page,all_count=all_count,per_page_num=10)
   page_queryset = book_list[page_obj.start:page_obj.end]
   return render(request,'booklist.html',locals())

4.前端使用方法

python 复制代码
<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            {% for book in page_queryset %}
            <p>{{ book.title }}</p>
            {% endfor %}
            {{ page_obj.page_html|safe }}
        </div>
    </div>
</div>
相关推荐
菜鸟的人工智能之路1 分钟前
极坐标气泡图:医学数据分析的可视化新视角
python·数据分析·健康医疗
菜鸟学Python2 分钟前
Python 数据分析核心库大全!
开发语言·python·数据挖掘·数据分析
小白不太白9504 分钟前
设计模式之 责任链模式
python·设计模式·责任链模式
运维-大白同学7 分钟前
将django+vue项目发布部署到服务器
服务器·vue.js·django
Estar.Lee8 分钟前
时间操作[取当前北京时间]免费API接口教程
android·网络·后端·网络协议·tcp/ip
喜欢猪猪9 分钟前
Django:从入门到精通
后端·python·django
一个小坑货9 分钟前
Cargo Rust 的包管理器
开发语言·后端·rust
bluebonnet2714 分钟前
【Rust练习】22.HashMap
开发语言·后端·rust
糖豆豆今天也要努力鸭15 分钟前
torch.__version__的torch版本和conda list的torch版本不一致
linux·pytorch·python·深度学习·conda·torch
何大春31 分钟前
【弱监督语义分割】Self-supervised Image-specific Prototype Exploration for WSSS 论文阅读
论文阅读·人工智能·python·深度学习·论文笔记·原型模式