ajax

一、多对多的三种创建方式

1、三种方式

  1、全自动(较为常用)

  2、纯手动(了解)

  3、半自动(推荐使用)

2、优缺点比较

  1、全自动:

    优点:第三张表自动帮你创建

    缺点:第三张表无法扩展额外的字段

  2、纯手动:

    优点:第三张表可以扩展额外的字段

    缺点:orm查询的时候会带来不便

  3、半自动:

    优点:第三张表可以扩展任意的额外字段 还可以利用orm 的正反向查询

    缺点:无法利用 add set remove clear方法,但是虽然你无法使用 你还可以自己直接操作第三张表,所以推荐使用半自动

3、简易代码演示

# 全自动

class Book(models.Model):
    title = models.CharField(max_length=32)
    authors = models.ManyToManyField(to='Author')  # 第三方表orm帮我们创建


class Author(models.Model):
    name = models.CharField(max_length=32)


# 纯手动
class Book(models.Model):
    title = models.ManyToManyField(max_length=32)


class Author(models.Model):
    name = models.CharField(max_length=32)


class Book2Author(models.Model):
    book = models.ForeignKey(to='Book')     # 书的外键字段,注意此时后面不用加_id因为django的orm会自动添加
    author = models.ForeignKey(to='Author')   # 作者表的外键字段,注意此时后面不用加_id因为django的orm会自动添加
    create_time = models.DateField(auto_now_add=True)


# 半自动
class Book(models.Model):
    title = models.ManyToManyField(max_length=32)
    authors = models.ManyToManyField(to='Author', through='Book2Author', through_fields=('book', 'author'))
    # 注意:多对多外键字段创在哪一方都可以,上面的这句话的意思是,告诉orm第三张表你不用帮我创了,我已经创好了through='Book2Author',告诉他我的第三张表是哪一个,
    #  through_fields=('book', 'author')是告诉orm我的哪两个字段是外键字段,然后你去给我绑定关系即可,因为字段可能有多个


class Author(models.Model):
    name = models.CharField(max_length=32)
    books = models.ManyToManyField(to='Book', through='Book2Author', through_fields=('author', 'book'))    # 这是外键字段绑在作者表上的写法,
    # 总结:在那张下面绑定,through_fields=()中第一个参数就写那张表
class Book2Author(models.Model): book = models.ForeignKey(to='Book') # 书的外键字段,注意此时后面不用加_id因为django的orm会自动添加 author = models.ForeignKey(to='Author') # 作者表的外键字段,注意此时后面不用加_id因为django的orm会自动添加 create_time = models.DateField(auto_now_add=True)

二、Ajax

1、Ajax特点简单介绍(八个字)

  异步提交

    同步:任务提交之后原地等待任务返回的结果  从进程表现上来说   就好像是阻塞

    异步:任务提交之后不需要原地等地等待返回结果  直接执行下一行代码  从进程表现上来说   非阻塞

  局部刷新

2、Ajax简介

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

  AJAX 不是新的编程语言,而是一种使用现有标准的新方法。

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

AJAX 不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。

  • 整个过程中页面没有刷新,只是刷新页面中的局部位置而已!
  • 当请求发出后,浏览器还可以进行其他操作,无需等待服务器的响应!

3、Ajax常见应用场景

  搜索引擎根据用户输入的关键字,自动提示检索关键字。

  还有一个很重要的应用场景就是注册时候的用户名的查重。

  其实这里就使用了AJAX技术!当文件框发生了输入变化时,使用AJAX技术向服务器发送一个请求,然后服务器会把查询到的结果响应给浏览器,最后再把后端返回的结果展示出来

  • 整个过程中页面没有刷新,只是局部刷新了;
  • 在请求发出后,浏览器不用等待服务器响应结果就可以进行其他操作;

4、Ajax优缺点

优点:

  • AJAX使用JavaScript技术向服务器发送异步请求;
  • AJAX请求无须刷新整个页面;
  • 因为服务器响应内容不再是整个页面,而是页面中的部分内容,所以AJAX性能高; 
  • 两个关键点:1.局部刷新,2.异步请求

5、与后端进行交互的方式

  1、浏览器窗口输入url    然后回车                           GET

  2、a标签href属性填写url    点击                              GET

  3、form表单                                                            GET/POST

  4、Ajax                     GET/POST

  注意: Ajax并不是一门语言  它其实就是基于js写的一个功能模块而已

     由于原生的js书写Ajax较为繁琐,所以这里我们直接学jQuery封装好的Ajax模块操作

三、初始Ajax以及Ajax的基本语法结构

1、一个小案列初始Ajax

  需求:页面上有三个input框   一个按钮   用户在前面两个框中输入数字   点击按钮保证页面不刷新的情况下,

     将数据发送给后端做计算,再将计算好的结果发送给前端展示到第三个input框中。

"""day55 URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.11/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.conf.urls import url, include
    2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^index/', views.index),
]
urls.py
from django.shortcuts import render, HttpResponse, redirect, reverse

# Create your views here.

def index(request):
    if request.method == 'POST':   # 因为是post请求所以需要去把配置文件中中间件的第四行注释掉
        i1 = request.POST.get('i1')
        i2 = request.POST.get('i2')

        # 注意现在i1和i2是字符串类型  需要先做类型转换
        i3 = int(i1) + int(i2)
        return HttpResponse(i3)
    return render(request, 'index.html')
Views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>

</head>
<body>
<input type="text" id="i1"> + <input type="text" id="i2"> = <input type="text" id="i3">
<button id="d1">按钮</button>


{#{* 给按钮添加绑定事件 *}#}
<script>
    $('#d1').click(function () {
        //获取两个框的内容 朝后端提交异步请求

        // ajax基本语法
        $.ajax({
            //1、到底朝那个后端提交数据
            url:'',  //控制数据的提交路径   也有三种写法跟form表单的action属性一致
            //2、指定当前的请求方式
            type:'post',
            //3、指定提交的数据
            data:{'i1':$('#i1').val(), 'i2':$('#i2').val()},
            //4、ajax是异步提交 所以需要给一个回调函数来处理返回的结果
            success:function (data) {//固定接收一个形参data  data就是异步提交的返回结果
                {#alert(data)#}
                //将异步回调的结果通过DOM操作渲染到第三个input框中
                $('#i3').val(data)
            }
        })
    })
</script>
</body>
</html>
index.html

- 演示图

 2、ajax基本语法结构

// ajax基本语法
        $.ajax({
            //1、到底朝那个后端提交数据
            url:'',  //控制数据的提交路径   也有三种写法跟form表单的action属性一致
            //2、指定当前的请求方式
            type:'post',
            //3、指定提交的数据
            data:{'i1':$('#i1').val(), 'i2':$('#i2').val()},
            //4、ajax是异步提交 所以需要给一个回调函数来处理返回的结果
            success:function (data) {//固定接收一个形参data  data就是异步提交的返回结果
                {#alert(data)#}
                //将异步回调的结果通过DOM操作渲染到第三个input框中
                $('#i3').val(data)
            }
        })

四、content-Type前后端传输数据的编码格式

1、提交数据的三种编码 格式

  urlencoded

  formdata

  application/json

2、演示form与ajax的content-Type参数

  a、form 表单

   1、默认是以urlencoded编码格式传输数据

    2、urlencoded的数据格式

     xxx=xxx&yyy=yyy

     django 后端针对该格式的数据,会自动解析帮你打包到request.POST中

    3、formdata数据格式

     django后端针对符合urlencoded编码格式(普通键值对)的数据还是统一解析到request.POST中

     而针对formdata文件数据就会自动解析放到request.FILES中

 b、ajax提交

    1、ajax默认的也是urlencoded编码格式

     2、ajax也可以发送json(这个form表单发送不了)

    注意:前后端数据交互  编码格式与数据格式一定要一致 ,不可以骗人家!!!明明你要发送的是json格式的数据,你跟我吼一声说你要发送列表了。 

      application/json

    django后端针对json格式的数据,并不会做任何的处理,而是直接放到request.body中, 我们也需要掌握ajax发json格式的基本结构代码

$.ajax({
             url:'',
             type:'post',
             //修改content-Type参数
             contentType:'application/json',
             data:JSON.stringify({'username':'yafeng', 'password': 123}),//将数据序列化成json格式数据
             success:function (data) {
                 alert(data)
             }

         })

    3、ajax发送文件 

      借助于内置对象FormData

      ajax发送文件的基本语法结构

既发普通键值对也发文件
            // ajax发送文件数据  需要借助于内置对象
            $('#d3').click(function () {
                // 1 需要先生成一个内置对象
                var myFormData = new FormData();
                // 2 传普通键值对  当普通键值对较多的时候 我们可以利用for循环来添加
                myFormData.append('username','jason');
                myFormData.append('password',123);
                // 3 传文件
                myFormData.append('myfile',$('#i1')[0].files[0]);  // 获取input框内部用户上传的文件对象
                // 发送ajax请求
                $.ajax({
                    url:'',
                    type:'post',
                    data:myFormData,
                    // 发送formdata对象需要指定两个关键性的参数

                    processData:false,  // 让浏览器不要对你的数据进行任何的操作
                    contentType:false,  // 不要使用任何编码格式 对象formdata自带编码格式并且django能够识别该对象

                    success:function (data) {
                        alert(data)
                    }
                })
            })

- 代码演示

"""day55 URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.11/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.conf.urls import url, include
    2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^index/', views.index),
    url(r'^ab_ct/', views.ab_ct),
]
urls.py
from django.shortcuts import render, HttpResponse, redirect, reverse

# Create your views here.

def index(request):
    if request.method == 'POST':   # 因为是post请求所以需要去把配置文件中中间件的第四行注释掉
        i1 = request.POST.get('i1')
        i2 = request.POST.get('i2')

        # 注意现在i1和i2是字符串类型  需要先做类型转换
        i3 = int(i1) + int(i2)
        return HttpResponse(i3)
    return render(request, 'index.html')


import json
def ab_ct(request):
    if request.method == 'POST':
        # print(request.POST)
        # print(request.FILES)
        # print(request.body)
        # 自己处理json格式的数据
        # 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) # 注:json.loads可以自动帮你解码,所以上面一步可以简写
        # print(json_dict, type(json_dict))


        print(request.POST)
        print(request.FILES)
    return render(request, 'ab_ct.html')
Views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>

</head>
<body>
{#<form action="" method="post" enctype="multipart/form-data">#}
{#    <input type="text" name="username">#}
{#    <input type="text" name="password">#}
{#    <input type="file" name="myfile">#}
{#    <input type="submit">#}
{#</form>#}

<button id="d1">点击发送ajax请求</button>

<button id="d2">ajax发送json数据格式</button>

<input type="file" name="myfile" id="i1">
<button id="d3">ajax发送文件数据</button>

<script>

    /*ajax 默认格式
    $('#d1').click(function () {
        $.ajax({
            url:'',
            type:'post',
            data:{'username': 'yafeng', 'password': 123},
            success:function (data) {
                alert(data)
            }
        })
    })

     */

    //发json格式数据
    /*
    $('#d2').on('click', function () {
         $.ajax({
             url:'',
             type:'post',
             //修改content-Type参数
             contentType:'application/json',
             data:JSON.stringify({'username':'yafeng', 'password': 123}),//将数据序列化成json格式数据
             success:function (data) {
                 alert(data)
             }

         })
    })

     */

    // ajax发送文件数据需要借助于 内置对象FormData
    $('#d3').click(function () {
        //1、需要先生成一个内置对象
        var myFormDate = new FormData();
        //2、传普通键值对
        myFormDate.append('username','yafeng');
        myFormDate.append('password', 123);
        //3、传文件
        myFormDate.append('myfile', $('#i1')[0].files[0])  //先变成原生json对象  再获取input框内部用户上传的文件对象
        //4、发送ajax请求
        $.ajax({
            url:'',
            type:'post',
            data:myFormDate,
            //发送formdata对象需要指定两个关键字的参数
            processData:false,// 让浏览器不要对你的数据进行任何的操作
            contentType:false,// 不要使用任何编码格式 对象formdata自带编码格式并且django能够识别该对象

            success:function (data) {
                alert(data)
            }
        })

    })
    
</script>
</body>
</html>
ab_ct.html

五、Django内置的序列化功能

Django内置的序列功能借助 serializers 模块,可以序列化对象

以前我们将后端将数据传递给前端通过json序列化

复制代码
from app01 import models
import json
​
def xlh(request):
    book_query = models.Book.objects.all()
    book_list = []
    for book_obj in book_query:
        book_list.append({
            'name': book_obj.name,
            'price': book_obj.price
        })
    res = json.dumps(book_list)
    return render(request, 'xlh.html', locals())
复制代码

我们可以使用Django内置的序列化功能模块 serializers ,直接序列化,展示的结果更加多将类名,主键都能拿到

复制代码
from django.core import serializers
​
def xlh(request):
    book_query = models.Book.objects.all()
    res = serializers.serialize('json', book_query)
return HttpResponse(res)
# [{"model": "app01.book", "pk": 1, "fields": {"name": "jason", "price": "123"}}]
复制代码

六、批量插入数据

我们之前学过的批量插入数据方式通过for循环再利用create方法,但是每次都要走数据库,效率很低

def insert_data(request):
    for i in range(1,501):
        models.Book.objects.create(name='第%s本书'%i)
    book_query = models.Book.objects.all()
    return render(request, 'insert.html', locals())
  # 每次循环一次都需要去数据库插入一条,500条大约需要一分钟

我们可以通过先将数据添加到一个列表中再使用 bulk_create 方法插入数据,这样就只会走一次数据库,效率很高

复制代码
def insert_data(request):
    book_list = []
    for i in range(1,9999):
        book_list.append(models.Book(name='新添加的第%s书'%i))
    models.Book.objects.bulk_create(book_list)  # 批量插入数据
    book_query = models.Book.objects.all()
    return render(request, 'insert.html', locals())
  # 效率很高,大约1秒插入9999条数据
复制代码

七、自定义分页器及使用

1、先引用分页器组件,封装好的类,存入本地文件夹中

 分页器组件

后端代码:

复制代码
# 获取当前页码,默认为1
current_page = request.GET.get('page', 1)
# 获取总页数
all_count = book_queryset.count()
# 生成一个自定义分页器类对象
page_obj=Pagination(current_page=current_page,all_count=all_count,pager_count=9)
# 针对真实的queryset数据进行切片操作
page_queryset = book_queryset[page_obj.start:page_obj.end]
return render(request,'ab_bc.html',locals())
复制代码

前端代码:

{{ page_obj.page_html|safe }}

八、Ajax结合sweetalert实现删除二次确认

1、首先需要从sweetalert 连接找到Bootstrap-sweetalert包,将包下载到本地

我们只需要使用dist文件中的 js 和 css 文件

2、从sweetalert forBootstrap中找到需要使用的样式,引用其代码

我们以删除二次确认为例:

后端代码:

复制代码
from django.http import JsonResponse
import time
def show_user(request):
    """
    前后端如果是通过ajax进行交互 那么交互的媒介一般情况下都是一个字典
    """
    if request.method == 'POST':
        # 模仿删除等待效果
        time.sleep(3)
        # 定义一个字典,通过Ajax传给后端的data
        back_dic = {"code":1000,'msg':''}
        # 拿到需要删除的数据id
        delete_id = request.POST.get('delete_id')
        # 将数据删除
        models.Userinfo.objects.filter(pk=delete_id).delete()
        back_dic['msg'] = '删除成功,准备跑路!!!'
        # 以json数据格式将字典返回给前端Ajax中的data
        return JsonResponse(back_dic)
    user_queryset = models.Userinfo.objects.all()
    return render(request,'show_user.html',locals())
复制代码

前端代码:

首先需要引入sweetalert文件中的css和js文件

复制代码
    {% load  static %}
    <link rel="stylesheet" href="{% static 'dist/sweetalert.css' %}">
    <script src="{% static 'dist/sweetalert.min.js' %}"></script>
    {# 删除中文文字宽度不够,找到文字标签修改大小#}
    <style>
        div.sweet-alert h2 {
            padding-top: 10px;
        }
    </style>
复制代码

调用sweetalert中样式代码,加以修改

复制代码
<script>
    // 给删除按钮绑定点击事件
    $('.cancel').click(function () {
        // 定义变量指代某一条数据
        var $aEle = $(this);
        // 引用sweetalert中的删除样式代码
        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:'',
                        type:'post',
                        data:{'delete_id':$aEle.attr("data_id")},
                        success:function (data) {  // 回调函数会自动将二进制的json格式数据 解码并反序列成js中的数据类型
                            if (data.code == 1000){
                                swal("删了!", "你准备跑路吧!", "success");
                                // 方式1  删除后自动刷新网页
                                // window.location.reload()
                                // 方式2 DOM操作动态修改,将删除的那条数据移除
                                $aEle.parent().parent().remove()  // 将标签直接移除
                            }else{
                                swal('发生了未知的错误', "error");
                            }
                        }
                    });
                    
                } else {
                    swal("怂笔", "你成功的刷新我对你的认知", "error");
                }
            });
    })
</script>
复制代码

    

  

    

  

原文地址:https://www.cnblogs.com/yafeng666/p/12181567.html