首页 > 技术文章 > Django--ajax

attila 2019-03-05 15:38 原文

一 . Ajax简介  

AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步的Javascript和XML”。
  即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML,现在更多使用json数据)。 Ajax不是一种能新的编程语言,它是使用现有标准的新方法. Ajax最大的优点就是不重新加载整个页面就可以与服务器交换数据,并更新部分网页内容(在用户不知不觉中就完成了) Ajax是异步交互
Ajax不影响页面发送其他请求

   下面看一下登录页面实际操作

  

   

 1  HTML文件
 2 {% load static %}
 3 <!DOCTYPE html>
 4 <html lang="en">
 5 <head>
 6     <meta charset="UTF-8">
 7     <title>login</title>
 8     <!--bootstrap-->
 9     <link href="{% static 'bootstrap/css/bootstrap.min.css'%}" rel="stylesheet">
10     <link rel="stylesheet" href="{% static 'cssfiles/login.css' %}">
11 
12 </head>
13 <body>
14 <div class="container">
15     <div style="margin-top: 100px"></div>
16     <div class="row">
17         <div class="col-md-4 col-md-offset-4">
18             {% csrf_token %}    <!--这个必须有-->
19             <input id="username" type="text" class="form-control" placeholder="请输入用户名">
20             <input id="password" type="password" class="form-control" placeholder="请输入密码">
21             <button id="sub"  class="btn btn-primary btn-lg btn-block">登 录</button>
22             <div id="fail"></div>
23         </div>
24     </div>
25 </div>
26 
27 <script src="{% static 'jsfiles/jquery.js' %}"></script>
28 
29 <script>
30     $('#sub').click(function () {
31         var uname = $('#username').val();
32         var pwd = $('#password').val();
33         var csrf_token = $('input[name=csrfmiddlewaretoken]').val();
34         //$.ajax({必须是键值对})
35         $.ajax({
36             url:"{% url 'login' %}",  //这个是必须有的
37             type:'post',             //这个是提交方式,必须有
38             data:{'username':uname, 'password':pwd, 'csrfmiddlewaretoken':csrf_token},
39             success:function (response) {  //这个response就是一个形参,接收视图中return后面传过来的数据
40                 if (response.status){
41                     location.href = response.home_url  //location.href的作用就是:如果走到这里就直接跳转页面
42                 }
43                 else{
44                     $('#fail').text('账号或密码不正确,请重新确认')
45                 }
46             }
47         })
48     })
49 </script>
50 </body>
51 </html>
HTML文件

 

 1 from django.shortcuts import render,HttpResponse
 2 from app_01 import models
 3 from django.http import JsonResponse
 4 from django.urls import reverse
 5 import json
 6 # Create your views here.
 7 
 8 def home(request):
 9     return render(request,'home.html')
10 
11 def login(request):
12     if request.method == 'GET':
13         return render(request, 'login.html')
14     else:
15         a = {'status':None, 'home_url':None}
16         # ajax提交数据
17         username = request.POST.get('username')  # get 后面的是Ajax里面的data的键
18         password = request.POST.get('password')
19         ret = models.UserMsg.objects.filter(username=username, password=password)
20         if ret.exists():
21             a['status'] = True
22             a['home_url'] = reverse('home')
23             # 方法一,这种方式只能传字典
24             return JsonResponse(a)
25             # 要想传其他类型(如列表)需要在a后面加上safe = False
26             return JsonResponse(a, safe=False)
27             # 方法二 方法三 见图ajax_json
28         else:
29             return HttpResponse('fail') 
视图(views)文件

 

 

  方法二

  

  方法三

  

 

二 . Ajax文件上传

   请求头ContentType(请求体的编码类型,常见类型有三种)

  1. application/x-www-form-urlencoded  

最常见的就是POST方式提交, form表单提交,如果不设置enctype属性, 默认为 application/x-www-from-urlencoded方式提交数据,
ajax 也是默认的这个.

  2. multipart/form-data

这也是POST数据提交的一种方式,必须要form表单中的enctype等于multipart/form-data,
上传文件的时候需要用这种enctype模式.

  3. application/json  

form 表单不支持json类型的Content-Type数据类型,但是ajax支持,而且现在越来越多的人把application/json  这个Content-Type作为响应头
这也是为什么ajax被广泛应用的原因,ajax还可以自己加请求头,这点也是ajax受欢迎的原因之一. 除了低版本的IE以外,其他的各大浏览器都支持
原生JSON.stringify.

  如果ajax里面写上这个contentType,那个data数据必须是json字符串类型,contentType:'json',只写这个他也能识别application/json类型

  

  

django不认识json,他只能识别application/x-www-form-urlencoded 和 multipart/form-data, 
所以如果需要拿到json的数据类型需要自己写逻辑

  

   基于form表单的文件上传

<form action="{% url 'upload' %}" method="post" enctype="multipart/form-data">  <!--这个enctype类型是传文件用的-->
                {% csrf_token %}
                <div class="form-group">
                    <input type="text" class="form-control"  placeholder="请输入用户名" name="username">
                </div>
                <div class="form-group">
                    <input type="file"  name="file">   <!--type='file'是上传文件-->
                </div>
                <button type="submit" class="btn btn-default">提交</button>
            </form>

  视图(views.py)

def upload(request):
    if request.method == 'GET':
        return render(request, 'upload.html')
    else:
        file = request.FILES.get('file')  # 获取文件对象
        print('>>>>>', file)   # 打印出来显示的是文件名字,但是是一个文件对象
        print('==>', type(file))  # <class 'django.core.files.uploadedfile.InMemoryUploadedFile'>, 一个文件对象,可以理解为一个文件句柄
        file_name = file.name  #  这个是真正的名字(字符串)
        print('>>>文件名', file_name,type(file_name))
        import os
        from upload import settings
        path = os.path.join(settings.BASE_DIR, 'statics', 'image', file_name)  # 存文件的路径,statics/image/file_name
        with open(path, 'wb') as f:
            # for data in file:
            #     f.write(data)
            for chunks in file.chunks():  # 默认一次返回2.5M,是一个生成器(常用)
                f.write(chunks)
        return HttpResponse('OK')

 

  

  基于Ajax上传文件

 1 {% load static %}
 2 <!DOCTYPE html>
 3 <html lang="en">
 4 <head>
 5     <meta charset="UTF-8">
 6     <title>Title</title>
 7     <!--bootstrap-->
 8     <link href="{% static 'bootstrap/css/bootstrap.min.css' %}" rel="stylesheet">
 9 
10 </head>
11 <body>
12     <div class="container">
13     <div style="margin-top: 100px"></div>
14     <div class="row">
15         <div class="col-md-6 col-md-offset-3">
16             <div class="form-group">
17                     <input id="username" type="text" class="form-control"  placeholder="请输入用户名" name="username">
18                 </div>
19                 <div class="form-group">
20                     <input id="file" type="file"  name="file">  <!--type='file'是上传文件-->
21                 </div>
22                 <button type="submit" class="btn btn-default">提交</button>
23         </div>
24     </div>
25 </div>
26 <script src="{% static 'jsfiles/jquery.js' %}"></script>
27 <script src="{% static 'jsfiles/jquery.cookie.js' %}"></script>
28 <script>
29     $('button[type=submit]').click(function () {
30         var formdata=new FormData();
31         var name = $('#username').val();
32         var file = $('#file')[0].files[0];  //先转换成dom文件再取索引
33         {#// 要是以下面这种形式添加csrf认证,上面需要用form表单,里面要写 {% csrf_token %}#}
34         // var csrf_token = $("input[name='csrfmiddlewaretoken']").val();
35         // formdata.append("csrfmiddlewaretoken", csrf_token);
36         formdata.append('username', name);
37         formdata.append('file', file);
38         $.ajax({
39             url:"{% url 'upload_ajax' %}",
40             type:'post',
41             data:formdata,
42             headers: {
43                 "X-CSRFToken": $.cookie('csrftoken')
44             }, // 这种方式添加csrf认证
45             processData:false,  //不处理数据
46             contentType:false,  // 不设置内容类型
47             success:function (response) {
48                 if (response.status){
49                     location.href = response.home_url
50                 }
51             }
52         })
53     })
54 </script>
55 </body>
56 </html>
HTML文件

 

 1 def upload_ajax(request):
 2     if request.method == 'GET':
 3         return render(request, 'upload_ajax.html')
 4     else:
 5         a = {'status': None, 'home_url': None}
 6         print(request.POST)
 7         username = request.POST.get('username')
 8         file = request.FILES.get('file')
 9         print('>>>>>', file)
10         print('==>', type(file))
11         file_name = file.name
12         print('>>>文件名', file_name, type(file_name))
13         import os
14         from upload import settings
15         path = os.path.join(settings.BASE_DIR, 'statics', 'image', file_name)
16         with open(path, 'wb') as f:
17             # for data in file:
18             #     f.write(data)
19             for chunks in file.chunks(): # 默认一次返回2.5M,是一个生成器
20                 f.write(chunks)
21         a['status'] = True
22         a['home_url'] = reverse('home')
23         return JsonResponse(a, safe=False)
视图(views)

 

   

 

 

  

 

推荐阅读