码迷,mamicode.com
首页 > Web开发 > 详细

Django与Ajax

时间:2019-03-27 21:16:22      阅读:303      评论:0      收藏:0      [点我收藏+]

标签:中文   BMI   小结   imp   app   jquery   场景   short   跳转   

Ajax简介

什么是Ajax

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

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


Ajax应用场景

登录注册时的校验,以百度为例
技术图片
当输入框失去焦点时,触发事件,浏览器发送Ajax请求,服务端进行校验,返回数据给浏览器,显示相应的错误信息
技术图片
此过程中,整个页面是没有刷新的,同时请求发出后我们还可以进行其他操作,因此是异步的,这就体现了Ajax的两大特点: 异步请求局部刷新


Ajax流程

Ajax请求的流程如下
技术图片

  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

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')


编写HTML页面

login.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>



密码正确时


技术图片



密码错误时


技术图片


小结

Ajax语法

发送Ajax请求的语法为:$.ajax({ }),大括号里放Ajax请求的四要素


Ajax请求四要素

  • url: 发送请求的网址
  • type:请求的类型,注意不是method
  • data: 要发送的数据,是一个javascript对象,可以带上csrfmiddlewaretoken键值对
  • 响应状态(通常是success)及回调函数


需要注意的地方

  • 前端页面发送Ajax请求时要带上csrfmiddlewaretoken,否则会返回403
  • 视图函数里登录成功后不能直接跳转,应返回一个字典(记录状态)交给前端页面完成跳转
  • 返回字典之前要序列化(json.dumps())
  • 前端页面跳转使用window.location.href = ‘/index/‘



ajax还有其他参数,可以设置,如下:

<button class="send_Ajax">send_Ajax</button>
<script>

       $(".send_Ajax").click(function(){

           $.ajax({
               url:"/handle_Ajax/",
               type:"POST",
               data:{username:"Yuan",password:123},
               success:function(data){
                   console.log(data)
               },
               
               error: function (jqXHR, textStatus, err) {
                        console.log(arguments);
                    },

               complete: function (jqXHR, textStatus) {
                        console.log(textStatus);
                },

               statusCode: {
                    '403': function (jqXHR, textStatus, err) {
                          console.log(arguments);
                     },

                    '400': function (jqXHR, textStatus, err) {
                        console.log(arguments);
                    }
                }

           })

       })

</script>

响应错误时,会执行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控制台打印的信息

<QueryDict: {'csrfmiddlewaretoken': ['NDVAZXADXpgRUA3IcHXRU3egH3oK8Ql0HWBNVkAWD43UnTgrPUNFPXV1mTE0hZ9I'], 'user': ['']}>
<MultiValueDict: {'img': [<InMemoryUploadedFile: 闭嘴.gif (image/gif)>]}>

这次得到了img信息,它的类型为MultiValueDict。描述了图片的文件名以及图片类型jpeg


存储文件

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

修改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(file_obj.name, 'wb') as f:
            for line in file_obj:
                f.write(line)  # 写入文件

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



重新上传,查看控制台打印信息

<QueryDict: {'csrfmiddlewaretoken': ['RmIJ3Eknj2NRN352dgz5F1JoQMgNC0NoLFoWZ1kGZHAUgmiLQtpTAVq9vCw3L9B6'], 'user': ['']}>
<MultiValueDict: {'img': [<InMemoryUploadedFile: 闭嘴.gif (image/gif)>]}>
闭嘴.gif
<class 'django.core.files.uploadedfile.InMemoryUploadedFile'>
闭嘴.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

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="/static/plugins/js/jquery.js"></script>
</head>
<body>

{#<h3>form表单文件上传</h3>#}
{# 表单默认为application/x-www-form-urlencoded。它的数据格式为key1=value1&key1=value1形式。 #}
{#<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>#}



<h3>Ajax上传文件</h3>
{% csrf_token %}

<form action="">
    <input type="text" id="username">
    <input type="file" id="avatar">
    <input type="button" id="ajax-submit" value="ajax提交">
</form>


<script>
    $('#ajax-submit').click(function () {
        var csrf = $("[name=csrfmiddlewaretoken]").val();
        console.log(csrf);
        var formdata = new FormData;
        //给当前FormData对象添加一个键值对
        formdata.append("csrfmiddlewaretoken", csrf);
        formdata.append("username", $('#username').val());
        //$('#avatar')[0]表示input标签
        //$('#avatar')[0].files表示获取到的文件列表
        //$('#avatar')[0].files[0]表示文件对象
        //要上传其他类型的文件,把img改成file就行,当然views里面对应的也要改
        formdata.append('img', $('#avatar')[0].files[0]);

        $.ajax({
            url: '', //表示当前路径
            type: 'post',
            //发送一个FormData对象
            data: formdata,
            //告诉jQuery不处理数据,默认是true,会把数据转化成&uname=abc&pwd=123的形式
            processData: false,
            //告诉jQuery不设置内容类型
            contentType: false,
            success: function (data) {
                data = JSON.parse(data);
                if (data["status"] == true) {
                    alert('上传成功!');
                    window.location.href='/file_upload/';
                } else {
                    alert('上传失败!')
                }

            }
        })
    })
</script>

</body>
</html>


小结

form表单上传文件要点

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

Ajax上传文件要点

  • 使用FormData对象发送文件数据(把FormData对象设为data的值)
  • FormData对象添加数据用formdata.append(key,value)的形式
  • 需要加上processData: falsecontentType: false来告诉jQuery不处理数据,不设置内容类型

Django与Ajax

标签:中文   BMI   小结   imp   app   jquery   场景   short   跳转   

原文地址:https://www.cnblogs.com/zzliu/p/10603452.html

(0)
(4)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!