• 巨蟒python全栈开发django11:ajax&&form表单上传文件contentType


    回顾:

    什么是异步?

    可以开出一个线程,我发出请求,不用等待返回,可以做其他事情.

    什么是同步?

    同步就是,我发送出了一个请求,需要等待返回给我信息,我才可以操作其他事情.

    局部刷新是什么?

    通过jquery或者JavaScript直接操作dom,在不刷新页面的情况下.

    ajax的整个流程?

    上图是jquery的写法,操作ajax,还有一种是js的操作方法,然后还用不到(了解有这么个方法就行)

     

    上边是前端,后边是后端views.py

    运行:如下图,这样就登录成功了

    总结上边的ajax的写法?

    json是什么?

    json是各种语言进行交流的桥梁,进行各种语言相互之间的通信,都可以转换成json交流

     每种语言都有自己对应数据格式的json相关的方法接口

    python(json)&&js(JSON)

    JSON 比 XML 更小、更快,更易解析,JSON 是轻量级的文本数据交换格式,

    • JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation)
    • JSON 是轻量级的文本数据交换格式
    • JSON 独立于语言:JSON 使用 Javascript语法来描述数据对象,但是 JSON 仍然独立于语言和平台。JSON 解析器和 JSON 库支持许多不同的编程语言。 目前非常多的动态(PHP,JSP,.NET)编程语言都支持JSON。
    • JSON 具有自我描述性,更易理解

    1.contentType介绍

    思考上节课内容

    为什么经过后端的,views.py处理之后,尤其是方法JsonResponse处理之后,前端不在需要json处理,只是django特有的点

    这就是contentType搞的鬼!!!!!

    首先介绍ContentType的流程

    请求行,请求体,请求数据

    响应的是200OK状态码//加工,切割,

    django如何自动加工的?

    django内部有对应的消息处理结构,消息格式是有响应的判断,也就是"内容类型"

    request,META是拿到所有请求头里边的数据.

    数据格式对应这个相应的函数,数据最后封装到request.POST

    我们首先contentType里边对应的是什么,然后调用相关内容的"消息拼接格式"

    django最后加工放在了request.POST里边!!!django帮助我们进行处理了,这是一种解析规则

    服务端和客户端相互传输这种contentType,指定怎不需要自己解析,不指定需要自己解析

    上图得到的信息,是浏览器为了好看,帮助我们处理了一些信息,才形成这个样子的

    上图才是,没有处理过的信息

    上图是响应头里边的信息格式:

    我们要的是下图:(请求头里边的Content-Type)

    第二种数据加工格式,是加工大段的数据的.分成一段一段进行传输,今天用到的就有这个

    第一种书没有办法发送的

    第三种是传输json数据类型的

    今天我们讲的就是,自定制请求头,在ajax里边自定制,写headers

    contentType写在里边和外边都是可以的

    常用的也就是上边说的三种

     我们以json格式发送数据,现在以json字符串的格式进行发送

    将上边的login注释,新写一个在views.py

    前端中的ajax,如上图的写法,将原来的contentType原来的xxx encode改成了json模式,

     

    后端如上图的写法

    得到上边的状态码是403 Forbidden

    原因:在使用json发送数据的时候,不认识下面的格式

    修改:去掉前端的中间件

    注释settings.py下面的内容:中间件

    得到下边的结果:

    修改如下:

    结果:

     

    运行

    body拿到的是请求体里边请求的原始数据

     

    meta就是请求的所有数据大字典

    我们可以在元数据中找到,自定义的请求头数据

    我们也可以找到对应的数据是json格式的

    运行:

     

    我们对得到的数据线转换一下,再处理

     

    在后边添加上上content_type="application/json"

    登录之后,此时的响应头是下面的

     请求头依然是json

    我们需要自己写json的处理模块,django的原生是支持的dif

    2.csrf_token

    上边的处理都把,中间件给注释了,我们应该怎么处理这个问题?

    记住一点:服务端可以从cookie里边拿东西!!!

    这个地方需要一个插件:(jquery.cookie.js)

    下面导入模块:

    再说一遍:cookie是服务器给浏览器的一个东西

     

    headers里边的是objects类型,

    如果不加cookie这个引入,得到的结果是:

    放开这个引入:

    这时候,我们可以成功进入这个界面了

    3.form表单上传文件

    新建文件

    在新窗口中打开

    settings.py数据库配置

    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME':'ajax',     # 要连接的数据库,连接前需要创建好
            'USER':'root',    # 连接数据库的用户名
            'PASSWORD':'222',    # 连接数据库的密码
            'HOST':'127.0.0.1',       # 连接主机,默认本级
            'PORT':3306    #  端口 默认3306
        }
    }
    View Code

    settings.py里边的打印sql语句的logging配置

    LOGGING = {
        'version': 1,
        'disable_existing_loggers': False,
        'handlers': {
            'console':{
                'level':'DEBUG',
                'class':'logging.StreamHandler',
            },
        },
        'loggers': {
            'django.db.backends': {
                'handlers': ['console'],
                'propagate': True,
                'level':'DEBUG',
            },
        }
    }
    View Code

    静态文件配置

    STATIC_URL = '/static/'
    
    STATICFILES_DIRS=[
        os.path.join(BASE_DIR, 'statics'),
        # os.path.join(BASE_DIR, 'jingtaiwenjian'),
    ]
    View Code

    元组和列表都行

    在整个大项目下创建statics文件,

    放css样式,bootstrap&&jquery&&cookie

    在当前的项目下的__init__.py放下面的文件

    import pymysql
    pymysql.install_as_MySQLdb()
    # 意思就是用pymysql替换MySQLdb
    View Code

    文件上传的项目应该怎么写?

     创建upload.html文件

     在静态文件中引入js&&bootstrap

    引入文件

    写一个form表单

    upload.html基本格式:

    <body>
    
    <div class="container">
        <div class="row">
            <div class="col-md-6 col-md-offset-3"></div>
        </div>
    </div>
    
    </body>
    View Code

    将Form表单放入其中

    <body>
    
    <div class="container">
        <div class="row">
            <div class="col-md-6 col-md-offset-3">
                
                <form class="form-horizontal">
      <div class="form-group">
        <label for="inputEmail3" class="col-sm-2 control-label">Email</label>
        <div class="col-sm-10">
          <input type="email" class="form-control" id="inputEmail3" placeholder="Email">
        </div>
      </div>
      <div class="form-group">
        <label for="inputPassword3" class="col-sm-2 control-label">Password</label>
        <div class="col-sm-10">
          <input type="password" class="form-control" id="inputPassword3" placeholder="Password">
        </div>
      </div>
      <div class="form-group">
        <div class="col-sm-offset-2 col-sm-10">
          <div class="checkbox">
            <label>
              <input type="checkbox"> Remember me
            </label>
          </div>
        </div>
      </div>
      <div class="form-group">
        <div class="col-sm-offset-2 col-sm-10">
          <button type="submit" class="btn btn-default">Sign in</button>
        </div>
      </div>
    </form>
                
            </div>
        </div>
    </div>
    
    </body>
    View Code

    修改之后的upload.html代码

    <body>
    
    <div class="container">
        <div class="row">
            <div class="col-md-6 col-md-offset-3">
    
                <form class="form-horizontal" method="post" action="{% url upload %}">
                    {% csrf_token %}
                    <div class="form-group">
                        <label for="inputEmail3" class="col-sm-2 control-label">用户名</label>
                        <div class="col-sm-10">
                            <input type="text" class="form-control" id="inputEmail3" placeholder="用户名" name="username">
                        </div>
                    </div>
                    <div class="form-group">
                        <label for="inputPassword3" class="col-sm-2 control-label">头像</label>
                        <div class="col-sm-10">
                            <input type="file" class="form-control" id="inputPassword3" placeholder="文件">
                        </div>
                    </div>
                    <div class="form-group">
                        <div class="col-sm-offset-2 col-sm-10">
                            <button type="submit" class="btn btn-default">提交上传</button>
                        </div>
                    </div>
                </form>
    
            </div>
        </div>
    </div>
    
    </body>
    View Code

    views.py里边的代码

    from django.shortcuts import render,HttpResponse,redirect
    
    # Create your views here.
    
    def upload(request):
        if request.method=='GET':
            return render(request,'upload.html')
        else:
            return HttpResponse('ok')
    View Code

    运行项目:

    上边项目一直出错的原因,已经修改好了

    注意前面的url

     运行:

    得到的结果有一点偏移

     修改之后的upload.html

    {% load static %}
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta http-equiv="content-Type" charset="UTF-8">
        <meta http-equiv="x-ua-compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width" ,initial-scale="1">
        <!--上边这个表示手机版的调整尺寸-->
        <!--上述2个meta标签"必须"放在最前面,任何其他内容都必须跟随其后-->
        <title>Title</title>
        <link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css'%}">
    </head>
    <body>
    
    <div class="container">
        <div class="row">
            <div class="col-md-6 col-md-offset-3">
                <div id="d1" style="margin-top: 100px;"></div>
                <form class="form-horizontal" method="post" action="{% url 'upload' %}">
                    {% csrf_token %}
                    <div class="form-group">
                        <label for="inputEmail3" class="col-sm-2 control-label">用户名</label>
                        <div class="col-sm-10">
                            <input type="text" class="form-control" id="inputEmail3" placeholder="用户名" name="username">
                        </div>
                    </div>
                    <div class="form-group">
                        <label for="inputPassword3" class="col-sm-2 control-label">头像</label>
                        <div class="col-sm-10">
                            <input type="file" id="inputPassword3" placeholder="文件">
                        </div>
                    </div>
                    <div class="form-group">
                        <div class="col-sm-offset-2 col-sm-10">
                            <button type="submit" class="btn btn-default">提交上传</button>
                        </div>
                    </div>
                </form>
    
            </div>
        </div>
    </div>
    
    </body>
    </html>
    View Code

    点击提交:

    在文件里边添加名字

    点击"提交上传"

     

    服务端得到的结果是:

    只能够拿到名字,

    思考,如何将文件发送过来?

    这是我们需要修改views.py文件里边的获取方式

     运行:

     

    得到的结果没有发生变化,打印两个东西

    点击上传

     

    服务端得到的结果:

    这个"InMemoryUploadedFile"相当于是文件句柄

    看一下file_name是什么?

    运行:

    并没有变化

    file_name=file_obj.name

    最后得到的结果是:

    这时候,将文件写在了根目录下了

     chunks方法

    结果:

    这时候我们就得到了李小龙的照片了

    chunks是64kb

    upload.html完整代码

    {% load static %}
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta http-equiv="content-Type" charset="UTF-8">
        <meta http-equiv="x-ua-compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width" ,initial-scale="1">
        <!--上边这个表示手机版的调整尺寸-->
        <!--上述2个meta标签"必须"放在最前面,任何其他内容都必须跟随其后-->
        <title>Title</title>
        <link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css'%}">
    </head>
    <body>
    
    <div class="container">
        <div class="row">
            <div class="col-md-6 col-md-offset-3">
                <div id="d1" style="margin-top: 100px;"></div>
                <form class="form-horizontal" method="post" action="{% url 'upload' %}" enctype="multipart/form-data">
                    {% csrf_token %}
                    <div class="form-group">
                        <label for="inputEmail3" class="col-sm-2 control-label">用户名</label>
                        <div class="col-sm-10">
                            <input type="text" class="form-control" id="inputEmail3" placeholder="用户名" name="username">
                        </div>
                    </div>
                    <div class="form-group">
                        <label for="inputPassword3" class="col-sm-2 control-label">头像</label>
                        <div class="col-sm-10">
                            <input type="file" id="inputPassword3" placeholder="文件" name="file_obj">
                        </div>
                    </div>
                    <div class="form-group">
                        <div class="col-sm-offset-2 col-sm-10">
                            <button type="submit" class="btn btn-default">提交上传</button>
                        </div>
                    </div>
                </form>
    
            </div>
        </div>
    </div>
    
    </body>
    </html>
    View Code

    views.py完整代码:

    from django.shortcuts import render,HttpResponse,redirect
    
    # Create your views here.
    
    def upload(request):
        if request.method  == 'GET':
            return render(request,'upload.html')
        else:
            username=request.POST.get('username')
            # file_obj=request.POST.get('file_obj')
            file_obj=request.FILES.get('file_obj')
            print(request.FILES)
            print(username)
            print(file_obj,type(file_obj))
            file_name=file_obj.name
            # print(file_name)
            with open(file_name,'wb')as f:
                # 读取文件形式
                # for i in file_obj:
                #     # data=i.read()
                #     f.write(i)
                #django提供的chunks方法
                for chunk in file_obj.chunks():
                    f.write(chunk)
            return HttpResponse('ok')
    View Code

    先将套路的东西先写上,再写具体的项目

    4.ajax上传文件

    用页面发送ajax页面:

    {% load static %}
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta http-equiv="content-Type" charset="UTF-8">
        <meta http-equiv="x-ua-compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width" ,initial-scale="1">
        <!--上边这个表示手机版的调整尺寸-->
        <!--上述2个meta标签"必须"放在最前面,任何其他内容都必须跟随其后-->
        <title>Title</title>
            <link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css'%}">
    
    </head>
    <body>
    
    <div class="container">
        <div class="row">
            <div class="col-md-6 col-md-offset-3" >
                <div id="d1" style="..."></div>
    
                用户名: <input type="text" name="username">
                文件: <input type="file" name="file_obj">
    
                <button id="sub">上传</button>
            </div>
        </div>
    </div>
    
    </body>
    </html>
    View Code
    {% load static %}
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta http-equiv="content-Type" charset="UTF-8">
        <meta http-equiv="x-ua-compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width" ,initial-scale="1">
        <!--上边这个表示手机版的调整尺寸-->
        <!--上述2个meta标签"必须"放在最前面,任何其他内容都必须跟随其后-->
        <title>Title</title>
            <link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css'%}">
    
    </head>
    <body>
    
    <div class="container">
        <div class="row">
            <div class="col-md-6 col-md-offset-3" >
                <div id="d1" style="..."></div>
    
                用户名: <input type="text" name="username">
                文件: <input type="file" name="file_obj">
    
                <button id="sub">上传</button>
            </div>
        </div>
    </div>
    
    <script src="{% static 'js/jquery.js' %}"></script>
    <script>
        $("#sub").click(function () {
            var name=$("input[name=username]").val();
            var file=$("input[type=file]").val();
        })
    </script>
        
    </body>
    </html>
    View Code

    运行:得到如下结果

    原来的代码:

    处理之后得到的结果:

    这时候,我们分成了两行

     

    在浏览器中运算,得到如上结果

    通过js获取DOM文件对象,想办法,发给后端

    下面示例的完整代码:

    upload2.html

    {% load static %}
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta http-equiv="content-Type" charset="UTF-8">
        <meta http-equiv="x-ua-compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width" ,initial-scale="1">
        <!--上边这个表示手机版的调整尺寸-->
        <!--上述2个meta标签"必须"放在最前面,任何其他内容都必须跟随其后-->
        <title>Title</title>
            <link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css'%}">
    
    </head>
    <body>
    
    <div class="container">
        <div class="row">
            <div class="col-md-6 col-md-offset-3" >
                <div id="d1" style="..."></div>
    
                <div>
                    用户名: <input type="text" name="username">
                </div>
                <div>
                    文件: <input type="file" name="file_obj">
                </div>
    
                <button id="sub">上传</button>
            </div>
        </div>
    </div>
    
    <script src="{% static 'js/jquery.js' %}"></script>
    <script src="{% static 'js/jquery.cookie.js' %}"></script>
    <script>
        $("#sub").click(function () {
            var name=$("input[name=username]").val();
            var file=$("input[type=file]")[0].files[0];
            var formdata=new FormData();
            formdata.append('username',name);
            formdata.append('file_obj',file);
            {#jq发送文件#}
            $.ajax({
                url:"{% url 'upload'%}",
                type:'post',
                data:formdata,
                processData:false,    //不处理数据
                contentType:false,      //不设置内容类型,这两个false必须写否则会报错违法
                headers:{
                    'X-CSRFToken':$.cookie('csrftoken'),
                },
                success:function (response) {
                    
                }
            })
        })
    </script>
    
    </body>
    </html>
    View Code

    views.py

    from django.shortcuts import render,HttpResponse,redirect
    
    # Create your views here.
    
    def upload(request):
        if request.method  == 'GET':
            return render(request,'upload2.html')
        else:
            username=request.POST.get('username')
            # file_obj=request.POST.get('file_obj')
            file_obj=request.FILES.get('file_obj')
            print(request.FILES)
            print(username)
            print(file_obj,type(file_obj))
            file_name=file_obj.name
            # print(file_name)
            with open(file_name,'wb')as f:
                # 读取文件形式
                # for i in file_obj:
                #     # data=i.read()
                #     f.write(i)
                #django提供的chunks方法
                for chunk in file_obj.chunks():
                    f.write(chunk)
            return HttpResponse('ok')
    View Code

    下面要讲解的是将文件单独放在某个位置!!!

    5.上传文件梳理流程

    6.插件的简单使用&&补充

  • 相关阅读:
    String 类的常用方法都有那些?
    ArrayList、LinkedList、Vector 的区别。
    1.JDK,JRE,JVM三者关系
    ==与equals的区别
    [LeetCode#22]Generate Parentheses
    [LeetCode#20]Valid Parentheses
    [LeetCode#2]Add Two Numbers
    [LeetCode#1] Two Sum
    [LeetCode#9] Palindrome Number
    [LeetCode#7]Reverse Integer
  • 原文地址:https://www.cnblogs.com/studybrother/p/10484495.html
Copyright © 2020-2023  润新知