Django与Ajax

Ajax简介

什么是Ajax

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

  • 同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求;
  • 异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求。
    AJAX除了异步的特点外,还有一个就是:浏览器页面局部刷新;(这一特点给用户的感受是在不知不觉中完成请求和响应过程)

## Ajax应用场景 登录注册时的校验,以百度为例 ![](https://img2018.cnblogs.com/blog/1542801/201903/1542801-20190326205349008-802468394.png) 当输入框失去焦点时,触发事件,浏览器发送Ajax请求,服务端进行校验,返回数据给浏览器,显示相应的错误信息 ![](https://img2018.cnblogs.com/blog/1542801/201903/1542801-20190326205534125-1716891331.png) 此过程中,整个页面是没有刷新的,同时请求发出后我们还可以进行其他操作,因此是异步的,这就体现了Ajax的两大特点: `异步请求`和 `局部刷新`
## Ajax流程 Ajax请求的流程如下 ![](https://img2018.cnblogs.com/blog/1542801/201903/1542801-20190326205950026-2135596492.png) 1. 客户端触发异步操作 2. 创建新的XMLHttpRequest对象,这是ajax的核心 3. 通过send()方法实现与server的连接 4. 服务器端接收请求,并处理 5. 返回处理的结果,这个结果可以是XML文档、也可以是josn字符串(一般情况下josn就可以处理大部分的结果、而且相对的比较好操作) 6. 在客户端去接收服务器传回来的结果,并且通过javascript进行你想要的处理

小结

Ajax特点

  • 异步请求
  • 局部刷新

实例

Ajax登录验证

准备工作

新建一个项目ajaxDemo,创建一个APP,命名为app1

新建一个数据库ajaxdemo,增加User表模型
models.py

from django.db import models

# Create your models here.


class User(models.Model):
    username = models.CharField(max_length=32)
    password = models.CharField(max_length=32)

配置urls
urls.py

from django.contrib import admin
from django.urls import path, re_path
from app1 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('login/', views.login),
    path('index/', views.index),
]

### 编写视图函数 views.py ```python from django.shortcuts import render, HttpResponse, redirect from app1 import models import json # Create your views here.

def login(request):
if request.method == "POST":
username = request.POST.get('username')
password = request.POST.get('password')
response = {"status": False, "username": None, 'msg': None}
user_obj = models.User.objects.filter(username=username, password=password).first()
if user_obj:
response['status'] = True
response['username'] = username
else:
response['msg'] = '用户名或密码错误'
# 注意发送之前要序列化
return HttpResponse(json.dumps(response, ensure_ascii=False))
else:
return render(request, 'login.html')

def index(request):
return render(request, 'index.html')


<br>
### 编写HTML页面
login.html
```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>用户登录</title>
    <script src="/static/plugins/js/jquery.js"></script>
</head>
<body>

<form action="">
    {% csrf_token %}
    <p>用户名:<input type="text" name="username"></p>
    <p>密码:<input type="text" name="password"></p>
    <input type="button" class='btn' value="登录">
    <span class="error"></span>
</form>


<script>
    $('.btn').on('click', function () {
        $.ajax({
            url: '/login/',
            //注意这里的方式是type,不是method!!!
            type: 'post',
            data: {
                username: $("[name='username']").val(),
                password: $("[name='password']").val(),
                csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val(),
            },
            //成功之后执行回调函数
            success:function (data) {
            //反序列化
            console.log(data);
            //console.log(typeof data);
            data = JSON.parse(data);
            if (data['status'] == true) {
                //登录成功跳转到个人主页
                window.location.href = '/index/';
            } else {
                //登录失败显示错误信息
                $('.error').html(data['msg']).css('color','red');
            }

        }
        })
    })
</script>


</body>
</html>

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>个人主页</title>
</head>
<body>

<h3>欢迎来到个人主页</h3>

</body>
</html>

密码正确时
![](https://img2018.cnblogs.com/blog/1542801/201903/1542801-20190326214637742-925346363.gif)
密码错误时
![](https://img2018.cnblogs.com/blog/1542801/201903/1542801-20190326214647190-699313987.gif)
## 小结 ### Ajax语法 发送Ajax请求的语法为:`$.ajax({ })`,大括号里放Ajax请求的四要素
### Ajax请求四要素 - url: 发送请求的网址 - type:请求的类型,注意不是method - data: 要发送的数据,是一个javascript对象,可以带上csrfmiddlewaretoken键值对 - 响应状态(通常是success)及回调函数
### 需要注意的地方 - 前端页面发送Ajax请求时要带上csrfmiddlewaretoken,否则会返回403 - 视图函数里登录成功后不能直接跳转,应返回一个字典(记录状态)交给前端页面完成跳转 - 返回字典之前要序列化(json.dumps()) - 前端页面跳转使用`window.location.href = '/index/'`
ajax还有其他参数,可以设置,如下: ```html ```

响应错误时,会执行error中的代码。

当 AJAX 请求正在进行时,执行complete的代码。它可以做一个请求等待的效果!


## ajax文件上传 首先来看form表单上传文件 ### 上传文件

修改urls.py,增加路径file_upload

from django.contrib import admin
from django.urls import path, re_path
from app1 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('login/', views.login),
    path('index/', views.index),
    path('file_put', views.file_upload),
]


修改views.py,增加视图函数file_upload
def file_upload(request):
    if request.method == "POST":
        print(request.POST)
        return HttpResponse('ok')
    return render(request, 'file_upload.html')


在templates里面增加页面file_put.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<h3>form表单文件上传</h3>
<form action="" method="post" enctype="multipart/form-data">
    {% csrf_token %}
    <input type="text" name="user">
    <input type="file" name="img"><br/><br/>
    <input type="submit">
</form>


</body>
</html>


注意:enctype的类型不同,发送数据格式也会不同。

form表单enctype默认为application/x-www-form-urlencoded。它的数据格式为key1=value1&key1=value1形式。

它不能发送图片,那么需要指定为multipart/form-data才可以!


选中一个文件,提交

pycharm控制台打印的信息

<QueryDict: {'csrfmiddlewaretoken': ['MiMUVVMla9s9TJ6CVYV4JUiQ6FJFlvU7GBs7RiMEQOfcm2jlybLSEOZBLvZVuEIP'], 'user': ['']}>

可以看到request.POST里面并没有文件的信息,这是因为Django把文件单独封装到另一个属性里面了,这就是request.FILS


修改视图函数
def file_upload(request):
    if request.method == "POST":
        print(request.POST)
        print(request.FILES)
        return HttpResponse('ok')
    return render(request, 'file_upload.html')


查看pycharm控制台打印的信息 ```python ]}>
这次得到了img信息,它的类型为MultiValueDict。描述了图片的文件名以及图片类型jpeg

<br>
### 存储文件

以上完成了从浏览器上传的部分,但是服务器接收之后还得对文件进行处理如存放等操作

修改file_upload视图函数

```python
def file_upload(request):
    if request.method == "POST":
        print(request.POST)
        print(request.FILES)  # 打印文件信息

        file_obj = request.FILES.get('img')
        print(file_obj)
        print(type(file_obj))  # 打印file_obj对象属性
        print(file_obj.name)

        with open(file_obj.name, 'wb') as f:
            for line in file_obj:
                f.write(line)  # 写入文件

        return HttpResponse('ok')
    return render(request, 'file_upload.html')


重新上传,查看控制台打印信息 ```python ]}> 闭嘴.gif 闭嘴.gif ```

左侧目录下出现了一张图片

因为没有指定路径,所以默认是项目根目录


### 指定路径存储

在项目根目录下新建statics文件夹,再在statics目录下新建imgs文件夹

修改file_upload视图函数

def file_upload(request):
    if request.method == "POST":
        print(request.POST)
        print(request.FILES)  # 打印文件信息

        file_obj = request.FILES.get('img')
        print(file_obj)
        print(type(file_obj))  # 打印file_obj对象属性
        print(file_obj.name)

        with open('statics/imgs/' + file_obj.name, 'wb') as f:
            for line in file_obj:
                f.write(line)  # 写入文件

        return HttpResponse('ok')
    return render(request, 'file_upload.html')

再次上传文件,就保存在了指定的目录


再来看Ajax上传文件

利用Ajax和FormData实现页面无刷新的文件上传效果,主要用到了jQuery的ajax()方法和XMLHttpRequest Level 2的FormData接口。

修改视图函数file_upload

def file_upload(request):
    # form表单上传
    # if request.method == "POST":
    #     print(request.POST)
    #     print(request.FILES)  # 打印文件信息
    # 
    #     file_obj = request.FILES.get('img')
    #     print(file_obj)
    #     print(type(file_obj))  # 打印file_obj对象属性
    #     print(file_obj.name)
    #     # 图片读取出来是二进制形式
    #     with open('statics/imgs/' + file_obj.name, 'wb') as f:
    #         for line in file_obj:
    #             f.write(line)  # 写入文件
    # 
    #     return HttpResponse('ok')
    # return render(request, 'file_upload.html')
    
    # Ajax上传文件
    if request.method == "POST":
        print(request.POST)
        print(request.FILES)  # 打印文件信息
        
        file_obj = request.FILES.get('img')  # 获取img对象
        print(file_obj, type(file_obj))
        print(file_obj.__dict__)
        print(file_obj.name)
        
        # 返回给ajax回调函数的数据
        response = {"status": False}
        with open('statics/imgs/' + file_obj.name, 'wb') as f:
            for line in file_obj:
                # write的返回值是写入的字符长度
                ret = f.write(line)
                # 判断写入的文件是否为空,不为空时才把status置为True
                if ret:
                    response["status"] = True
        return HttpResponse(json.dumps(response))  # 返回json数据
        

修改file_upload.html ```html Title

{#

form表单文件上传

#}
{# 表单默认为application/x-www-form-urlencoded。它的数据格式为key1=value1&key1=value1形式。 #}
{#
#}
{# {% csrf_token %}#}
{# #}
{#

#}
{# #}
{#
#}

Ajax上传文件

{% csrf_token %}
<br>

## 小结
### form表单上传文件要点
- 需在form表单设置enctype="multipart/form-data"然后用submit提交
- 视图函数里用request.FILES.get('file')获取文件对象
- 服务端接收到文件对象后对其逐行读取并写入新文件

### Ajax上传文件要点
- 使用FormData对象发送文件数据(把FormData对象设为data的值)
- FormData对象添加数据用`formdata.append(key,value)`的形式
- 需要加上`processData: false`和`contentType: false`来告诉jQuery不处理数据,不设置内容类型
posted @ 2019-03-27 20:27  乘月归  阅读(157)  评论(0编辑  收藏  举报