AJAX

JSON

JSON是JavaScript对象表示法(JavaScript Object Notation)。

img

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>

效果如下:

img

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

通过开发者工具F12查看contentTpye类型。

  • form表单:默认提交数据编码格式是urlencoded
    • urlencoded数据格式是username=admin&password=123,Django后端自动解析并打包给request.POST方法。
    • formdata数据格式Django后端也会自动解析,但是数据放在request.FILES中。
  • 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>

效果如下:

img

利用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>

效果如下:

img

AJAX+SweetAlert插件示例

示例地址:https://lipis.github.io/bootstrap-sweetalert/

img

# 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>
原文地址:https://www.cnblogs.com/daizongqi/p/11756018.html