Title

Ajax的简单使用介绍

一.多对多关系创建的三种方式

1)全自动(较为常用)

1 class Book(models.Model)
2     titile = models.CharField(max_length=32)
3     
4     # 通过Django的ManyToManyField类方法快速创建第三张中间表
5     authors = models.ManyToManyField(to='author')
6     
7     
8 class Author(models.Model)
9     name = CharField(max_length=32)
  • 优点:自动创建第三章表,快速

  • 缺点:第三张表只有三个字段,无法添加其余的字段

2)纯手动

 1 class Book(models.Model)
 2     titile = models.CharField(max_length=32)
 3  4     
 5     
 6 class Author(models.Model)
 7     name = CharField(max_length=32)
 8     
 9     
10 # 手动创建第三张表并添加外键关系    
11 class Book2Author(models.Model)
12     book = models.ForeignKey(to='Book')
13     author=models.ForeignKey(to='Author')
14     create_time = models.DateField(auto_now_add=True)
  • 优点:第三张表可以添加自己的扩展字段

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

2)半自动(推荐使用)  

 1 class Book(models.Model)
 2     titile = models.CharField(max_length=32)
 3     # 需要建一个外键字段,额外添加两个参数,through表示通过那一张表来表示第三张表,through_field表示哪两个字段是用来链接的
 4         authors = models.ManyToManyField(to='author',through=‘Book2Author’, through_fields=('book', 'author'))
 5     
 6      
 7 class Author(models.Model)
 8     name = CharField(max_length=32)
 9     
10   
11 12 class Book2Author(models.Model)
13     book = models.ForeignKey(to='Book')
14     author=models.ForeignKey(to='Author')
15     create_time = models.DateField(auto_now_add=True)

 

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

  • 缺点:无法利用add,set,remove,claer这些方法

虽然无法使用了 但是你还可以自己直接操作第三表

二.Ajax介绍

1)什么是Ajax?

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

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

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

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

简单概括就是:异步提交,局部刷新

  • 同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求;

  • 异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求。任务的结果是是通过异步回调机制 callback()

  • 与后端交互的方法:

交互方式请求方式
1.浏览器窗口输入回车 get
2.a标签href属性填写url点击 get
3.form表单 get/post
4.Ajax get/post

Ajax并不是一门新的语言 它其实就是基于js写的一个功能模块而已 由于原生js书写ajax较为繁琐 所以我们直接学jQuery封装号的ajax模块操作

2)Ajax的语法

举例:

需求:

 1 # views.py
 2 def index(request):
 3     if request.method == 'POST':
 4         i1 = request.POST.get('i1')
 5         i2 = request.POST.get('i2')
 6         # i1 和 i2 是字符串类型  需要先做类型转换
 7         i3 = int(i1) + int(i2)
 8         return HttpResponse(i3)
 9     return render(request,'index.html')
10
 1 # index.py
 2  3 <input type="text" id="i1"> + <input type="text" id="i2"> = <input type="text" id="i3">
 4 <button id="d1">按钮</button>
 5 <script>
 6     //绑定事件
 7     $('#d1').click(function () {
 8         // 获取两个框里面内容 朝后端提交异步请求
 9         // ajax基本语法
10         $.ajax({
11             // 1.到底朝哪个后端提交数据
12             url:'',  // 控制数据的提交路径  有三种写法 跟form表单的action属性一致
13             // 2.指定当前请求方式
14             type:'post',
15             // 3.提交的数据
16             data:{'i1':$('#i1').val(),'i2':$('#i2').val()},
17             // 4.ajax是异步提交 所以需要给一个回调函数来处理返回的结果
18             success:function (data) {  // data就是异步提交的返回结果
19                 // 将异步回调的结果通过DOM操作渲染到第三个input框中
20                 $('#i3').val(data)
21             }
22         })
23     })
24 </script>

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

  • urlencoded

  • formdata

  • application/json

1).form表单提交的数据

默认是urlencoded编码格式传输数据 urlencoded数据格式:username=jason&password=123

1 # 简单代码
2 <form action="" method="post">
3     <p></p>
4     <p></p>
5     <input type="text" name="username">
6     <input type="text" name="password">
7     <input type="submit" >
8    

 

 

 

 

 

 

 

补充:django后端针对该格式的数据 会自动解析并帮你打包到request.POST中以键值对的形式存在

取出数据的方式:

if request.method == 'POST':    print(request.POST)
    
# <QueryDict: {'username': ['ajska'], 'password': ['123']}>

若再form表单中的enctype属性是以默认urlencoded格式,input中type属性是file格式,上传文件,只是上传的文件名,具体文件内容并没有上传上去,只有将格式改为form-data格式,通过request.files才能拿到最终数据,并且此时在网页中通过检查也无法轻易获取数据了

<form action="" method="post" enctype="multipart/form-data">
    <input type="file" name="myfile">

formdata数据格式还是可以传普通送键值对数据 ,django后端针对符合urlencoded编码格式数据(普通键值对)还是统一解析到request.POST中 而针对formdata文件数据就会自动解析放到request.FILES中

2)ajax提交的数据

前后端数据交互 编码格式与数据格式一定要一致

  • 默认也是urlnecoded编码格式

 1 <script>
 2  3     $('#d1').click(function () {
 4         $.ajax({
 5             url:'',
 6             type:'post',
 7             data:{'username':'jason','password':123},
 8             success:function (data) {
 9                 alert(data)
10             }
11         })
12     })
13  </script>

  • 但是Ajax也能发送application/json格式数据

     1 $('#d2').on('click',function () {
     2         $.ajax({
     3             url:'',
     4             type:'post',
     5             // 修改content-Type参数
     6             contentType:'application/json',
    //通过JSON.stringify出来成json格式
    7 data:JSON.stringify({'username':'jason','password':123}), // 将数据序列化成json格式字符串 8 success:function (data) { 9 alert(data) 10 } 11 }) 12 })

      

此时后端无法拿到数据

1 def ab_ct(request):
2     if request.method == 'POST':
3         print(request.POST)
4         print(request.FILES)

数据已经传到requset.body中了

print(request.body)

这个数据既不在POST中,也不在FILES中,以json格式存在body中

我们可以自己解码反序列化拿到数据

1 # 自己处理json格式数据
2 json_bytes = request.body
3 # 先解码
4 json_str = json_bytes.decode('utf-8')
5 # 再反序列化
6 json_dict = json.loads(json_str)
7 #补充:json.loads能够自动解码并序列化
8 json_dict = json.loads(json_bytes)
9 print(json_dict,type(json_dict))

  • ajax也能提交文件格式

 1 <input type="file" name="myfile" id="i1">
 2 <button id="d3">ajax发送文件数据</button>
 3 <script>
 4  $('#d3').click(function () {
 5         // 1 需要先借助new方法生成一个内置对象
 6         var myFormData = new FormData();
 7         // 2 传普通键值对  当普通键值对较多的时候 我们可以利用for循环来添加
 8         myFormData.append('username','jason');
 9         myFormData.append('password',123);
10         // 3 传文件
11         myFormData.append('myfile',$('#i1')[0].files[0]);  // 获取input框内部用户上传的文件对象
12         // 发送ajax请求
13         $.ajax({
14             url:'',
15             type:'post',
16             data:myFormData,
17             // 发送formdata对象需要指定两个关键性的参数
18 19             processData:false,  // 让浏览器不要对你的数据进行任何的操作
20             contentType:false,  // 不要使用任何编码格式 对象formdata自带编码格式并且django能够识别该对象
21 22             success:function (data) {
23                 alert(data)
24             }
25         })
26     })
27 </script>



28 def ab_ct(request): 29 if request.method == 'POST': 30 print(request.POST) 31 print(request.FILES) 32 return render(request,'ab_ct.html')

三.django内置序列化

举例:

 1 def ab_se(request):
 2     # 拿到所有数据库的对象集
 3     user_queryset = models.Userinfo.objects.all()
 4     user_list = []
 5     for user_obj in user_queryset:
 6         user_list.append({
 7             'username':user_obj.username,
 8             'password':user_obj.password,
 9             'gender':user_obj.get_gender_display(),
10         })
11      # 变成json格式
12     res = json.dumps(user_list)    
13     return render(request,'ab_se.html',locals())
14    
<body>
{{ res }}
</body>

将数据库里面的数据通过json序列化 变成大字典的形式就是序列化

通过 http://www.bejson.com/ 这个网站可以在线校验

以上操作完全可以用Django的内置序列化模块 serializers处理,并且处理的更好

1 from app01 import models
2 from django.core import serializers
3 def ab_se(request):
4     user_queryset = models.Userinfo.objects.all()
5     # 传入需要修改的格式,以及需要序列化的对象集合
6     res = serializers.serialize('json',user_queryset) 
7     return HttpResponse(res)

四:Django批量插入

1).普通批量插入

 1 def ab_bc(request):
 2     # 先插入1000条件数据
 3     for i in range(1,1001):
 4         models.Book.objects.create(title='第%s本书'%i)
 5     book_queryset = models.Book.objects.all()
 6     return render(request,'ab_bc.html',locals())
 7 </head>
 8 <body>
 9 {% for book_obj in page_queryset %}
10     <p>{{ book_obj.title }}</p>
11 {% endfor %}
12 </body>

2)快速批量插入

 1 def ab_bc(request):
 2     book_list = []
 3     for i in range(1,10001):
 4         book_list.append(models.Book(title='新的%s书'%i))
 5     models.Book.objects.bulk_create(book_list)  # 批量插入数据的方式
 6     book_queryset = models.Book.objects.all()
 7     return render(request,'ab_bc.html',locals())
 8 </head>
 9 <body>
10 {% for book_obj in page_queryset %}
11     <p>{{ book_obj.title }}</p>
12 {% endfor %}
13 </body>

五.自定义分页器

分页器模板

  1 class Pagination(object):
  2     def __init__(self,current_page,all_count,per_page_num=2,pager_count=11):
  3         """
  4         封装分页相关数据
  5         :param current_page: 当前页
  6         :param all_count:    数据库中的数据总条数
  7         :param per_page_num: 每页显示的数据条数
  8         :param pager_count:  最多显示的页码个数
  9         
 10         用法:
 11         queryset = model.objects.all()
 12         page_obj = Pagination(current_page,all_count)
 13         page_data = queryset[page_obj.start:page_obj.end]
 14         获取数据用page_data而不再使用原始的queryset
 15         获取前端分页样式用page_obj.page_html
 16         """
 17         try:
 18             current_page = int(current_page)
 19         except Exception as e:
 20             current_page = 1
 21  22         if current_page <1:
 23             current_page = 1
 24  25         self.current_page = current_page
 26  27         self.all_count = all_count
 28         self.per_page_num = per_page_num
 29  30  31         # 总页码
 32         all_pager, tmp = divmod(all_count, per_page_num)
 33         if tmp:
 34             all_pager += 1
 35         self.all_pager = all_pager
 36  37         self.pager_count = pager_count
 38         self.pager_count_half = int((pager_count - 1) / 2)
 39  40     @property
 41     def start(self):
 42         return (self.current_page - 1) * self.per_page_num
 43  44     @property
 45     def end(self):
 46         return self.current_page * self.per_page_num
 47  48     def page_html(self):
 49         # 如果总页码 < 11个:
 50         if self.all_pager <= self.pager_count:
 51             pager_start = 1
 52             pager_end = self.all_pager + 1
 53         # 总页码  > 11
 54         else:
 55             # 当前页如果<=页面上最多显示11/2个页码
 56             if self.current_page <= self.pager_count_half:
 57                 pager_start = 1
 58                 pager_end = self.pager_count + 1
 59  60             # 当前页大于5
 61             else:
 62                 # 页码翻到最后
 63                 if (self.current_page + self.pager_count_half) > self.all_pager:
 64                     pager_end = self.all_pager + 1
 65                     pager_start = self.all_pager - self.pager_count + 1
 66                 else:
 67                     pager_start = self.current_page - self.pager_count_half
 68                     pager_end = self.current_page + self.pager_count_half + 1
 69  70         page_html_list = []
 71         # 添加前面的nav和ul标签
 72         page_html_list.append('''
 73                     <nav aria-label='Page navigation>'
 74                     <ul class='pagination'>
 75                 ''')
 76         first_page = '<li><a href="?page=%s">首页</a></li>' % (1)
 77         page_html_list.append(first_page)
 78  79         if self.current_page <= 1:
 80             prev_page = '<li class="disabled"><a href="#">上一页</a></li>'
 81         else:
 82             prev_page = '<li><a href="?page=%s">上一页</a></li>' % (self.current_page - 1,)
 83  84         page_html_list.append(prev_page)
 85  86         for i in range(pager_start, pager_end):
 87             if i == self.current_page:
 88                 temp = '<li class="active"><a href="?page=%s">%s</a></li>' % (i, i,)
 89             else:
 90                 temp = '<li><a href="?page=%s">%s</a></li>' % (i, i,)
 91             page_html_list.append(temp)
 92  93         if self.current_page >= self.all_pager:
 94             next_page = '<li class="disabled"><a href="#">下一页</a></li>'
 95         else:
 96             next_page = '<li><a href="?page=%s">下一页</a></li>' % (self.current_page + 1,)
 97         page_html_list.append(next_page)
 98  99         last_page = '<li><a href="?page=%s">尾页</a></li>' % (self.all_pager,)
100         page_html_list.append(last_page)
101         # 尾部添加标签
102         page_html_list.append('''
103                                            </nav>
104                                            </ul>
105                                        ''')
106         return ''.join(page_html_list)
分页器模板

使用方式

先在app01下面新建一个utils文件夹,并在其中建一个mypage.py文件,再将上面的模版复制进文件中

 1 from app01.utils.mypage import Pagination
 2 def ab_bc(request):
 3     # 先插入1000条件数据
 4     book_list = []
 5     for i in range(1,10001):
 6         book_list.append(models.Book(title='新的%s书'%i))
 7     models.Book.objects.bulk_create(book_list)  # 批量插入数据的方式
 8     book_queryset = models.Book.o   
 9     # 获取当前页
10     current_page = request.GET.get('page', 1)
11     # 数据总条数
12     all_count = book_queryset.count()
13     # 1 现生成一个自定义分页器类对象
14     page_obj = Pagination(current_page=current_page,all_count=all_count,pager_count=9)
15     # 2 针对真实的queryset数据进行切片操作
16     page_queryset = book_queryset[page_obj.start:page_obj.end]
17     return render(request,'ab_bc.html',locals())bjects.all()
使用方式views.py
1 <body>
2 {% for book_obj in page_queryset %}
3     <p>{{ book_obj.title }}</p>
4 {% endfor %}
5  <!--渲染页面-->
6 {{ page_obj.page_html|safe }}
7 </body>
8 </html>
html文件中

六.Ajax结合sweetalert实现二次删除

前期准备: 下载项目文件

建立一个satatic文件夹将此文件导入,在html文件中导入文件路径

 1 # views.py
 2  3 from django.http import JsonResponse  # 可以实现返回一个字典
 4 import time
 5 def show_user(request):
 6     """
 7     前后端如果是通过ajax进行交互 那么交互的媒介一般情况下都是一个字典
 8     :param request:
 9     :return:
10     """
11     if request.method == 'POST':
12         time.sleep(3)
13         
14         back_dic = {"code":1000,'msg':''}
15         
16         delete_id = request.POST.get('delete_id')
17         
18         models.Userinfo.objects.filter(pk=delete_id).delete()
19         
20         back_dic['msg'] = '删除成功,准备跑路!!!'
21         
22         return JsonResponse(back_dic)
23     user_queryset = models.Userinfo.objects.all()
24     return render(request,'show_user.html',locals())
views.py
 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6     <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
 7     <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
 8     <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
 9     {% load  static %}
10     <link rel="stylesheet" href="{% static 'dist/sweetalert.css' %}">
11     <script src="{% static 'dist/sweetalert.min.js' %}"></script>
12     <style>
13         div.sweet-alert h2 {
14             padding-top: 10px;
15         }
16     </style>
17 </head>
18 <body>
19 <div class="container">
20     <div class="row">
21         <div class="col-md-8 col-md-offset-2">
22             <h2 class="text-center">数据展示</h2>
23             <table class="table-hover table table-striped">
24                 <thead>
25                 <tr>
26                     <th>主键</th>
27                     <th>用户名</th>
28                     <th>密码</th>
29                     <th>性别</th>
30                     <th>操作</th>
31                 </tr>
32                 </thead>
33                 <tbody>
34                 {% for user_obj in user_queryset %}
35                     <tr>
36                         <td>{{ user_obj.pk }}</td>
37                         <td>{{ user_obj.username }}</td>
38                         <td>{{ user_obj.password }}</td>
39                         <td>{{ user_obj.get_gender_display }}</td>
40                         <td>
41                             <a href="#" class="btn btn-primary btn-xs">编辑</a>
42                             <a href="#" class="btn btn-danger btn-xs cancel" data_id="{{ user_obj.pk }}">删除</a>
43                         </td>
44                     </tr>
45                 {% endfor %}
46                 </tbody>
47 48             </table>
49         </div>
50     </div>
51 </div>
52 53 54 <script>
55     $('.cancel').click(function () {
56         var $aEle = $(this);
57         swal({
58                 title: "你确定要删吗?",
59                 text: "你如果删了,你可要准备跑路啊!",
60                 type: "warning",
61                 showCancelButton: true,
62                 confirmButtonClass: "btn-danger",
63                 confirmButtonText: "是的,老子就要删!",
64                 cancelButtonText: "惹不起惹不起!",
65                 closeOnConfirm: false,
66                 closeOnCancel: false,
67                 showLoaderOnConfirm: true
68             },
69             function (isConfirm) {
70                 if (isConfirm) {
71                     // 发送ajax请求
72                     $.ajax({
73                         url:'',
74                         type:'post',
75                         data:{'delete_id':$aEle.attr("data_id")},
76                         success:function (data) {  // 回调函数会自动将二进制的json格式数据 解码并反序列成js中的数据类型
77                             if (data.code == 1000){
78                                 swal("删了!", "你准备跑路吧!", "success");
79                                 // 方式1
80                                 {#window.location.reload()#}
81                                 // 方式2 DOM操作动态修改
82                                 $aEle.parent().parent().remove()  // 将标签直接移除
83                             }else{
84                                 swal('发生了未知的错误', "error");
85                             }
86                         }
87                     });
88 89                 } else {
90                     swal("怂笔", "你成功的刷新我对你的认知", "error");
91                 }
92             });
93     })
94 </script>
95 </body>
html文件
posted @ 2020-01-12 22:54  Mr江  阅读(460)  评论(0编辑  收藏  举报