巨蟒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 } }
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', }, } }
静态文件配置
STATIC_URL = '/static/' STATICFILES_DIRS=[ os.path.join(BASE_DIR, 'statics'), # os.path.join(BASE_DIR, 'jingtaiwenjian'), ]
元组和列表都行
在整个大项目下创建statics文件,
放css样式,bootstrap&&jquery&&cookie
在当前的项目下的__init__.py放下面的文件
import pymysql
pymysql.install_as_MySQLdb()
# 意思就是用pymysql替换MySQLdb
文件上传的项目应该怎么写?
创建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>
将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>
修改之后的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>
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')
运行项目:
上边项目一直出错的原因,已经修改好了
注意前面的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>
点击提交:
在文件里边添加名字
点击"提交上传"
服务端得到的结果是:
只能够拿到名字,
思考,如何将文件发送过来?
这是我们需要修改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>
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')
先将套路的东西先写上,再写具体的项目
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>
{% 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>
运行:得到如下结果
原来的代码:
处理之后得到的结果:
这时候,我们分成了两行
在浏览器中运算,得到如上结果
通过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>
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')
下面要讲解的是将文件单独放在某个位置!!!
5.上传文件梳理流程
6.插件的简单使用&&补充