Django 系列博客(十四)

Django 系列博客(十四)

前言

本篇博客介绍在 html 中使用 ajax 与后台进行数据交互。

什么是 ajax

ajax(Asynchronous Javascript And XML)翻译成中文就是‘’异步 JavaScript 和 XML‘’。即使用 JavaScript 语言与服务器进行异步交互,传输的数据为 XML(现在更多地使用 json)。

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

ajax 除了异步的特点外,还有一个就是:浏览器页面局部刷新。在页面没有进行刷新的情况下进行数据交互。

优点:

  • ajax 使用JavaScript 技术向服务器发送异步请求;
  • ajax 无需刷新整个页面。

基于 jQuery 的 ajax 实现

前端代码

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <script src="/static/jquery-3.3.1.js"></script>

    <title>regist</title>
{#    <link rel="stylesheet" href="/static/jquery-3.3.1.js">#}
</head>
<body>
<p>用户:<input type="text" id="name"></p>
<p>密码:<input type="password" id="pwd"></p>
<p>确认密码:<input type="password" id="tpwd"></p>
<input type="button" id="submit" value="提交"><span id="error"></span>
</body>

<script>

    $('#submit').click(function () {
        console.log($('#submit'));
        {#$.ajax({#}
        {#    url:'/regist/',#}
        {#    type:'post',#}
        {#    data:{name:$("#name").val(), pwd:$("#pwd").val(), tpwd:$("#tpwd")},#}
        {#    success:function (data) {#}
        {#        console.log(data)#}
        {#    }#}
        $.ajax({
            url:'/regist/',
            type:'post',
            data:{name:$("#name").val(), pwd:$("#pwd").val(), tpwd:$("#tpwd").val()},
            success:function (data) {
                console.log(data)
            }
        })

    })
</script>
</html>

后端代码

from django.http import JsonResponse
from django.shortcuts import render, redirect
from app01.models import *

# Create your views here.


def wrapper(func):
    def inner(*args, **kwargs):
        if args[0].method == 'GET':
            return func(*args, **kwargs)
        elif kwargs['contentType'] == 'application/json':
            import json
            args[0].POST = json.loads(args[0].body)
            return func(*args, **kwargs)
        else:
            return func(*args, **kwargs)
    return inner

import json
# json.loads()


def regist(request):
    dic = {'status': 200, 'msg': None}
    print(request.body)
    if request.method == 'GET':
        return render(request, 'regist.html')
    else:
        print('/////')
        print(request.POST, 'dddd')
        name = request.POST.get('name')
        pwd = request.POST.get('pwd')
        tpwd = request.POST.get('tpwd')

        user = UserInfo.objects.filter(name=name).first()
        if user:
            dic['status'] = 100
            dic['msg'] = '用户已存在'
            return JsonResponse(dic)
        else:
            if name and pwd and tpwd:
                if pwd == tpwd:
                    UserInfo.objects.create(name=name, pwd=pwd)
                    dic['msg'] = '注册成功'
                    return JsonResponse(dic)
                else:
                    dic['status'] = 101
                    dic['msg'] = '两次密码不一样'
                    return JsonResponse(dic)
            else:
                dic['status'] = 101
                dic['msg'] = '密码不正确'
                return JsonResponse(dic)


@wrapper
def login(request):
    dic = {'status': 200, 'msg': None}
    if request.method == 'GET':
        return render(request, 'login.html')
    else:
        name = request.POST.get('name')
        pwd = request.POST.get('pwd')

        user = UserInfo.objects.filter(name=name).first()
        if not user:
            dic['status'] = 100
            dic['msg'] = '用户不存在,请注册'
            return JsonResponse(dic)
        else:
            if pwd == user.pwd:
                dic['msg'] = '登陆成功'
                return JsonResponse(dic)
            else:
                dic['status'] = 101
                dic['msg'] = '密码错误'
                return JsonResponse(dic)

js代码

$("#submit3").click(function () {
            $.ajax({
                url: '/auth/',
                type: 'post',
                data: {
                    'user': $("#id_name").val(),
                    'password': $('#id_password').val()
                },

                success: function (data) {
                    {#console.log(data)#}
                    var data=JSON.parse(data)
                    if (data.user){
                        location.href='https://www.baidu.com'
                    }else {
                        $(".error").html(data.message).css({'color':'red','margin-left':'20px'})
                    }
                }


            })
        }
    )

文件上传

请求头

  1. application/x-www-form-urlencoded

这是最常见的 POST 提交数据的方式了。浏览器的原生

表单,如果不设置 enctype 属性,那么最终会以 application/x-www-form-urlencoded方式提交数据。类似于下面:

POST http://www.example.com HTTP/1.1
Content-Type: application/x-www-form-urlencoded;charset=utf-8

请求体
  1. multipart/form-data

当我们使用表单上传文件时,必须让表单的 enctype 等于multipart/form-data。

POST http://www.example.com HTTP/1.1
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA

------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="user"

yuan
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="file"; filename="chrome.png"
Content-Type: image/png

PNG ... content of chrome.png ...
------WebKitFormBoundaryrGKCBY7qhFd3TrwA--

这个例子稍微复杂点。首先生成了一个 boundary 用于分割不同的字段,为了避免与正文内容重复,boundary 很长很复杂。然后 Content-Type 里指明了数据是以 multipart/form-data 来编码,本次请求的 boundary 是什么内容。消息主体里按照字段个数又分为多个结构类似的部分,每部分都是以--boundary 开始,紧接着是内容描述信息,然后回车,最后是字段具体内容(文本或二进制)。如果传输的是文件,还要包含文件名和文件类型信息。消息主体最后以--boundary--表示结束。

这种方式一般用于上传文件,各大服务端语言也有很好的支持。

这两种POST 提交的方式,都是浏览器原生支持的,而且先阶段标准中原生表单也只支持这两种方式(通过元素的 enctype 属性指定,默认为 application/x-www-form-urlencoded)。随着越来越多的web站点尤其是 WebApp,全部使用 Ajax 进行数据交互之后,我们完全可以定义新的数据提交方式,给开发带来更多便利。

  1. application/json

application/json是另外一种请求头,不过更多的是作为响应头,因为 json 格式的数据时通用数据格式。不过目前也用来作为请求头,用来告诉服务器端主体是序列化后的 json 字符串。由于 json 规范的流行,除了低版本的 IE 之外的各大浏览器都原生支持 json.stringfy,服务器端语言也都有处理 json数据的函数,使用 json 不会遇到什么麻烦。

json 格式支持比键值对复杂的多的结构化数据,这点对数据传输很有用。

基于form表单上传文件

前端代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<form action="" method="post" enctype="multipart/form-data">
    <p>用户名:<input type="text" name="name"></p>
    <input type="file" name="myfile">
{#    <input type="file" name="myfile2">#}
    <input type="submit" value="提交">

</form>

</body>
</html>

后端代码

class UploadFile(View):

    def get(self, request):
        return render(request, 'upload_file.html')

    def post(self, request):
        file = request.FILES.get('myfile')
        # print(file['file'])
        from django.core.files.uploadedfile import InMemoryUploadedFile
        print(time.time())
        filename = str(time.time()).split('.')[0] + file.name
        with open(filename, 'wb') as f:
            for line in file:
                f.write(line)
        return HttpResponse('上传成功')

基于ajax 的文件上传

前端代码

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>uploadfile</title>
    <script src="/static/jquery-3.3.1.js"></script>
</head>
<body>
<p>用户名:<input type="text" id="name"></p>
<p>选择文件:<input type="file" id="my_file"></p>
<button id="btn">上传</button><span id="msg"></span>
</body>

<script>
    $('#btn').click(function () {
        var myfile = $('#my_file')[0].files[0];
        var formdata = new FormData();
        formdata.append('name', $('#name').val());
        formdata.append('myfile', myfile);
        $.ajax({
            url:'/uploadfile/',
            type:'post',
            processData:false, // 告诉 jQuery 不要处理发送的数据
            contentType:false, // 告诉 jQuery 不要设置 Content-Type 请求头
            data:formdata,
            success:function (data) {
                console.log(data);
                $('#msg').text(data)
            }
        })
    })

</script>
</html>

后端代码

MEDIA_PATH = '/Users/jingxing/Django/homework/paging/media'

def uploadfile(request):
    if request.method == 'GET':
        return render(request, 'uploadfile.html')
    else:

        myfile = request.FILES.get('myfile')
        print(myfile)
        filepath = os.path.join(MEDIA_PATH, myfile.name[32:-3]+'jpg')
        with open(filepath, 'wb') as f:
            for line in myfile:
                f.write(line)
        FileInfo.objects.create(name=request.POST.get('name'), filepath=filepath)
        return HttpResponse('上传成功')

ajax 提交 json 格式数据

前端代码

$('#submit1').click(function () {
        postdata={name1:$("#name").val(),pwd2:$("#pwd").val()}
        $.ajax({
            url:'/loginjson/',
            type:'post',
            // 指定提交的编码格式是json格式,
            contentType:'application/json',
            data:JSON.stringify(postdata),
            // data:postdata,
            // data:'123',
            success:function (data) {
                console.log(data)

            }
        })
    })

后端代码

def loginjson(request):
    dic={'status':100,'msg':None}
    if request.method=='POST':
        print(request.POST)
        print(request.GET)
        print(request.body)
        xx=request.body.decode('utf-8')
        # re是个字典{"name1":"lqz","pwd2":"123"}
        re=json.loads(xx)
        request.POST=11


        print(request.POST)
        #
        #
        # name=re.get('name1')
        # pwd=re.get('pwd2')
        # print(name)
        # print(pwd)
        return HttpResponse('ok')

后端返回 json 数据

前端代码

$('#submit').click(function () {
        $.ajax({
            url:'/login/',
            type:'post',
            data:{name1:$("#name").val(),pwd2:$("#pwd").val()},
            success:function (data) {
                //后台用JsonResponse返回数据
                //data 就会被转成字典
                console.log(data)
                console.log(typeof data)
                //JSON.parse(data) 把字符串类型转成字典
                data=JSON.parse(data)
                {#JSON.stringify()#}
                console.log(typeof dat1)
                if(data.status == 100){
                    //成功,跳转到指定页面
                    //location.href=地址,前端就会跳转到指定的url
                    alert(data.msg)
                    //$("#error").text(data.msg+'正在跳转')
                    //location.href=data.url
                }else{
                    $("#error").text(data.msg)
                }


            }
        })
    })

后端代码

def login(request):
    dic={'status':100,'msg':None}
    if request.method == 'GET':
        return render(request, 'login.html')
    # if request.is_ajax():
    if request.method=='POST':
        name=request.POST.get('name1')
        pwd=request.POST.get('pwd2')
        if name=='lqz' and pwd=='123':
            dic['msg'] = '登陆成功'
            # 想让前端跳转
            # dic['url']='http://www.baidu.com'
            dic['url']='/test/'
        else:
            # 返回json格式字符串
            dic['status']=101
            dic['msg']='用户名或密码错误'
        # return JsonResponse(dic)
        return HttpResponse(json.dumps(dic))

Django内置的序列化数据方法

from django.core import serializers

def test(request):
    book_list = Book.objects.all()
    ret = serializers.serialize('json', book_list)
    return HttpResponse(ret)
原文地址:https://www.cnblogs.com/zuanzuan/p/10294294.html