Django Ajax

水痕 2020-06-03

  • Ajax简介
  • ajax示例
  • 前后端传输数据的编码格式(contentType)
  • ajax发送json格式数据
  • ajax发送文件
  • django自带的序列化组件
  • 批量插入
  • 自定义分页器

Ajax简介

AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步的Javascript和XML”。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML)

  • AJAX 不是新的编程语言,而是一种使用现有标准的新方法。
  • AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。(这一特点给用户的感受是在不知不觉中完成请求和响应过程)

Ajax我们只学习jQuery封装之后的版本(不学原生的 原生的复杂并且在实际项目中也一般不用)

ajax示例

{# index.html #}

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
<input type="text" id="d1"> +
<input type="text" id="d2"> =
<input type="text" id="d3">
<p>
    <button id="btn">点我</button>
</p>

<script>
    // 先给按钮绑定一个点击事件
    $(‘#btn‘).click(function () {
        // 朝后端发送ajax请求
        $.ajax({
            // 1.指定朝哪个后端发送ajax请求
            url:‘‘, // 不写就是朝当前地址提交
            // 2.请求方式
            type:‘post‘,  // 不指定默认就是get 都是小写
            // 3.预期服务器返回的数据类型
            datatype: ‘json‘,
            // 4.数据
            data:{‘i1‘:$(‘#d1‘).val(),‘i2‘:$(‘#d2‘).val()},
            // 5.回调函数:当后端给你返回结果的时候会自动触发 args接受后端的返回结果
            success:function (data) {
                // 通过DOM操作动态渲染到第三个input里面#}
                $(‘#d3‘).val(data)

                // JSON.parse(data)
                // console.log(typeof data)

                // 针对后端如果是用HttpResponse返回的数据 回调函数不会自动帮你反序列化你要自己用JSON.parse反序列化或者设置datatype
               // 如果后端直接用的是JsonResponse返回的数据 回调函数会自动帮你反序列化

            }
        })
    })
</script>
</body>
</html>
# views.py

import json
from django.http import JsonResponse

def ab_ajax(request):
    if request.method == "POST":
        # print(request.POST)  # <QueryDict: {‘username‘: [‘jason‘], ‘password‘: [‘123‘]}>
        i1 = request.POST.get(‘i1‘)
        i2 = request.POST.get(‘i2‘)
        # 先转成整型再加
        i3 = int(i1) + int(i2)
        return HttpResponse(i3)

        # d = {‘code‘:100,‘msg‘:666}
        # 向前端传字典要序列化
        # return HttpResponse(json.dumps(d))
        # return JsonResponse(d)
    return render(request,‘index.html‘)

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

"""
我们主要研究post请求数据的编码格式
get请求数据就是直接放在url后面的 url?username=jason&password=123

可以朝后端发送post请求的方式
1.form表单
2.ajax请求

前后端传输数据的编码格式
1.urlencoded
2.formdata
3.json
"""
# form表单
默认的数据编码格式是urlencoded
数据格式:username=jason&password=123
django后端针对符合urlencoded编码格式的数据都会自动帮你解析封装到request.POST中
# request.POST>> username=jason&password=123

如果你把编码格式改成formdata,那么针对普通的键值对还是解析到request.POST中而将文件解析到request.FILES中

# form表单是没有办法发送json格式数据的


# ajax
默认的编码格式也是urlencoded
数据格式:username=jason&age=20
django后端针对符合urlencoded编码格式的数据都会自动帮你解析封装到request.POST中
# request.POST>> username=jason&age=20

ajax发送json格式数据

"""
1.前后端传输数据的时候一定要确保编码格式跟数据真正的格式是一致的!!!

2.前后端传输json数据在request.POST里面是找不到的,需要到request.body里找

3.django针对json格式的数据不会做任何的处理

4.request.is_ajax()判断当前请求是否是ajax请求 返回布尔值
"""

‘‘‘ab_json.html
<body>
<button class="btn btn-danger" id="d1">点我</button>
<script>
    $(‘#d1‘).click(function () {
        $.ajax({
            url:‘‘,
            type:‘post‘,
            data:JSON.stringify({‘username‘:‘jason‘,‘age‘:25}),
            contentType:‘application/json‘,  // 指定编码格式
            success:function () {

            }
        })
    })
</script>
</body>
‘‘‘

# views.py
def ab_json(request):
    if request.is_ajax():
        json_bytes = request.body
        # json_str = json_bytes.decode(‘utf-8‘)
        # json_dict = json.loads(json_str)

        # json.loads括号内如果传入了一个二进制格式的数据那么内部自动解码再反序列化
        json_dict = json.loads(json_bytes)
        print(json_dict,type(json_dict))  # {‘username‘: ‘jason‘, ‘age‘: 25} <class ‘dict‘>
    return render(request,‘ab_json.html‘)
"""
ajax发送json格式数据需要注意点
	1.contentType参数指定成:application/json
	2.数据是真正的json格式数据
	3.django后端不会帮你处理json格式数据需要你自己去request.body获取并处理
"""

ajax发送文件

"""
ajax发送文件需要借助于js内置对象FormData
"""
"""ab_file.html
<body>
<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>
</body>
"""

# views.py
def ab_file(request):
    if request.is_ajax():
        if request.method == ‘POST‘:
            print(request.POST)
            print(request.FILES)
    return render(request,‘ab_file.html‘)

"""
总结:
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自带的序列化组件

给前端返回列表套字典格式的数据

from django.http import JsonResponse
from django.core import serializers
def ab_ser(request):
    user_queryset = models.User.objects.all()
    # user_list = []
    # for user_obj in user_queryset:
    #     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)

    # 序列化
    res = serializers.serialize(‘json‘,user_queryset)
    """会自动帮你将数据变成json格式的字符串 并且内部非常的全面"""
    return HttpResponse(res)
"""
[
{   "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}}
]
"""

ajax结合sweetalert

<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>
                <td>{{ user_obj.get_gender_display }}</td>
                <td>
                    <button class="btn btn-primary btn-xs">编辑</button>
                    <button class="btn btn-danger btn-xs del" delete_id="{{ user_obj.pk }}">删除</button>
                </td>
            </tr>
        {% endfor %}
    </tbody>
</table>



<script>
    $(‘.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
        },
        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()#}
                            // 2.利用DOM操作 动态刷新
                            currentBtn.parent().parent().remove()
                        }else{
                            swal(‘完了‘,‘出现了位置的错误‘,‘info‘)
                        }
                    }

                })

          } else {
            swal("怂逼", "不要说我认识你", "error");
          }
        });
    })
</script>

批量插入

def ab_pl(request):
    # 先给Book插入一万条数据
    # for i in range(10000):
    #     models.Book.objects.create(title=‘第%s本书‘%i)
    # # 再将所有的数据查询并展示到前端页面
    # book_queryset = models.Book.objects.all() # 页面加载很慢

    # 批量插入
    book_list = []
    for i in range(100000):
        book_obj = models.Book(title=‘第%s本书‘%i)
        book_list.append(book_obj)
    models.Book.objects.bulk_create(book_list)
    return render(request,‘ab_pl.html‘,locals())

"""
当你想要批量插入数据的时候 使用orm给你提供的bulk_create能够大大的减少操作时间
"""

自定义分页器

# 自定义分页器
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)



# 前端使用
<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>




# 后端使用
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())

相关推荐

mmywcoco / 0评论 2020-06-06