一、视图层之请求对象——HttpRequest对象
1、request属性
django将请求报文中的请求行、请求头、请求体封装成HttpRequest类中的属性
# 1、HttpRequest.GET
一个类似于字典的对象,包含HTTP GET 的所有参数(详情参考QueryDict对象)
# 2、HttpRequest.POST
一个类似于字典的对象,日过请求中包括表单数据,则将这些数据封装成QueryDict对象
POST 请求可以带有空的 POST 字典 —— 如果通过 HTTP POST 方法发送一个表单,但是表单中没有任何的数据,QueryDict 对象依然会被创建。
因此,不应该使用 if request.POST 来检查使用的是否是POST 方法;应该使用 if request.method == "POST"
另外:如果使用 POST 上传文件的话,文件信息将包含在 FILES 属性中。
注意:键值对是多个的时候,比如checkbox类型的input标签、select标签,需要使用:request.POST.getlist('hobby')
# 3、HttpRequest.body
一个字符串,代表请求报文的主体。
在处理非HTTP形式的报文时非常有用,例如二进制图片、XML、Json数据等
但是,如果要处理表单数据的时候,推荐还是使用HttpRequest.POST
# 4、HttpRequest.path
一个字符串,用来表示请求的路径组件(不含域名)
例如:/index/home/
# 5、HttpRequest.method
一个字符串,表示请求使用的HTTP方法,必须要大写
例如:"GET"、"POST"
# 6、HttpRequest.encoding
一个字符串,表示提交的数据的编码方式(如果为None则表示使用的是DEFAULT_CHARSET 的设置,默认为"utf-8")
这个属性是可写的,即可以修改它来修改访问表单数据使用的编码
一旦修改,那么接下来对属性的任何访问(GET/POST中读取数据)都将使用新的encoding值
如果事先知道表单数据的编码不是DEFAULT_CHARSET ,那就使用它来修改
# 7、HttpRequest.META
一个标准的python字典,包含所有的HTTP头部,具体的头部信息取决于客户端和服务器
取值:
CONTENT_LENGTH—— 请求的正文的长度(是一个字符串)。
CONTENT_TYPE —— 请求的正文的MIME 类型。
HTTP_ACCEPT —— 响应可接收的Content-Type。
HTTP_ACCEPT_ENCODING —— 响应可接收的编码。
HTTP_ACCEPT_LANGUAGE —— 响应可接收的语言。
HTTP_HOST —— 客服端发送的HTTP Host 头部。
HTTP_REFERER —— Referring 页面。
HTTP_USER_AGENT —— 客户端的user-agent 字符串。
QUERY_STRING —— 单个字符串形式的查询字符串(未解析过的形式)。
REMOTE_ADDR —— 客户端的IP 地址。(*****)
REMOTE_HOST —— 客户端的主机名。
REMOTE_USER —— 服务器认证后的用户。
REQUEST_METHOD —— 一个字符串,例如"GET" 或"POST"。
SERVER_NAME —— 服务器的主机名。
SERVER_PORT —— 服务器的端口(是一个字符串
示例:
print(HttpRequest.META['REMOTE_ADDR'])
从上面可以看到,除 CONTENT_LENGTH 和 CONTENT_TYPE 之外,请求中的任何 HTTP 首部转换为 META 的键时,都会将所有字母大写并将连接符替换为下划线最后加上 HTTP_ 前缀。
所以,当一个叫做 X-Bender 的头部将转换成 META 中的 HTTP_X_BENDER 键。
# 8、HttpRequest.FILES
一个类似于字典的对象,包含所有的上传文件信息。
FILES 中的每个键为<input type="file" name="" /> 中的name,值则为对应的数据。
注意,FILES 只有在请求的方法为POST 且提交的<form> 带有enctype="multipart/form-data" 的情况下才会包含数据。否则,FILES 将为一个空的类似于字典的对象。
# 9、其他
- HttpRequest.COOKIES
一个字典,包含所有的cookie。(键、值都是字符串)
- HttpRequest.session
一个既可读又可写的类似于字典的对象,表示当前的会话。只有当Django 启用会话的支持时才可用。
完整的细节参见会话的文档。
- HttpRequest.user
一个 AUTH_USER_MODEL 类型的对象,表示当前登录的用户。
如果用户当前没有登录,user 将设置为 django.contrib.auth.models.AnonymousUser 的一个实例。你可以通过 is_authenticated() 区分它们。
2、request常用方法
# 1、HttpRequest.get_full_path()
返回path,如果可以将加上查询字符串
即返回请求的全路径,包含数据(不包含域名)
# 2、HttpRequest.is_ajax()
返回一个bull值,反映是不是ajax请求
如果请求是通过XMLHttpRequest 发起的,则返回True,方法是检查 HTTP_X_REQUESTED_WITH 相应的首部是否是字符串'XMLHttpRequest'。
大部分现代的 JavaScript 库都会发送这个头部。如果你编写自己的 XMLHttpRequest 调用(在浏览器端),你必须手工设置这个值来让 is_ajax() 可以工作。
如果一个响应需要根据请求是否是通过AJAX 发起的,并且你正在使用某种形式的缓存例如Django 的 cache middleware,
你应该使用 vary_on_headers('HTTP_X_REQUESTED_WITH') 装饰你的视图以让响应能够正确地缓存。
二、视图层之响应对象——HttpResponse对象
响应对象主要有三种形式:
HttpResponse()
render()
redirect()
from django.http import JsonResponse
def index(request):
# 三件套:
# return HttpResponse('ok')
# return render(request,'index.html',context={'name':'lqz','age':18})
# return redirect('/home') # 重定向自己的地址,重定向第三方地址,经常跟反向解析一起使用
# 第四种形式:JsonResponse()
# 向客户端返回json格式数据
// 方式一:
# import json
# res=json.dumps({'name':'张三','age':18},ensure_ascii=False)
# 有中文时注意设置ensure_ascii=False 防止乱码
# return HttpResponse(res)
// 方式二:
# django内置提供的JsonResponse,本质还是HttpResponse
return JsonResponse({'name':'张三'}, json_dumps_params={'ensure_ascii':False})
# 设置ensure_ascii的方式有区别于方式一
return JsonResponse(['aaa', 'bbb', 'ccc'], safe=False)
# safe:转换除字典以外的格式,需要设置safe=False
注意点:
1)301和302的区别。
301和302状态码都表示重定向,就是说浏览器在拿到服务器返回的这个状态码后会自动跳转到一个新的URL地址,这个地址可以从响应的Location首部中获取
(用户看到的效果就是他输入的地址A瞬间变成了另一个地址B)——这是它们的共同点。
他们的不同在于。301表示旧地址A的资源已经被永久地移除了(这个资源不可访问了),搜索引擎在抓取新内容的同时也将旧的网址交换为重定向之后的网址;
302表示旧地址A的资源还在(仍然可以访问),这个重定向只是临时地从旧地址A跳转到地址B,搜索引擎会抓取新的内容而保存旧的网址。 SEO302好于301
2)重定向原因:
(1)网站调整(如改变网页目录结构);
(2)网页被移到一个新地址;
(3)网页扩展名改变(如应用需要把.php改成.Html或.shtml)。
这种情况下,如果不做重定向,则用户收藏夹或搜索引擎数据库中旧地址只能让访问客户得到一个404页面错误信息,访问流量白白丧失;再者某些注册了多个域名的
网站,也需要通过重定向让访问这些域名的用户自动跳转到主站点等。
三、CBV和FBV
# CBV是基于类的视图(Class base view)
# FBV是基于函数的视图(Function base view)
在views.py中写视图类
from django.shortcuts import render, HttpResponse, redirect
## 第一步:写一个类,继承View
from django.views import View
class Index(View):
def get(self, request): # 当url匹配成功,get请求会执行它
return HttpResponse('ok')
def post(self, request):
return HttpResponse('post')
第二步:配置路由
path('index/', views.Index.as_view()),
四、文件上传
## html注意编码方式
<form action="/index/" method="post" enctype="multipart/formp-data">
<p>用户名:<input type="text" name="name"></p>
<p>密码:<input type="password" name="password"></p>
<p><input type="file" name="myfile"></p>
<p><input type="submit" value="提交"></p>
</form>
# views.py
from django.shortcuts import HttpResponse
def index(request):
file = request.FILES.get('myfile')
# 打开一个空文件夹,写入
with open(file.name, 'wb') as f:
for line in file.chunks():
f.write(line)
return HttpResponse('文件上传成功')
五、postman软件
模拟发送http请求(可以控制请求路径、请求方式、请求头、请求体)
六、form表单、提交地址
# 关于action
# ① 不写,默认向当前地址发送请求
# ② /index/
向当前域(http://127.0.0.1:8000/)的index/发送请求
# ③ http://127.0.0.1:8000/index/
向改地址发送请求(可以向第三方服务发送请求)
# 关于method
# ① post
发送post请求(默认编码情况下:以key=value&key=value的形式拼接到请求体中)
# ② get
发送get请求(以key=vulue&key=vlaue的形式拼接到路径中)
<form action="/index/" method="post">
<p>用户名:<input type="text" name="name"></p>
<p>密码:<input type="password" name="password"></p>
<p><input type="submit" value="提交"></p>
</form>
七、pycharm的自动提示
from django.core.handlers.wsgi import WSGIRequest
# pycharm的自动提示:写上下面的一行内容
request=request # type: WSGIRequest
八、cbv本质
#1、请求来了,路由匹配成功,执行path('index/', views.Index.as_view()),
就是执行views.Index.as_view()()
#2、本质是执行as_view()内部的闭包函数view()
#3、执行闭包函数view()--->执行dispatch()
#4、dispatch内部,根据请求的方法(get/post)---->执行视图类Index中的get函数/post函数
九、前后端交互编码方式
1、 urlencoded---->传普通的数据,form表单默认的就是这种--->request.POST
2、form-data------>传文件和数据-------->request.POST request.FILES
3、json----------->传json格式的数据---->request.body中取出来自行处理
def index(request):
# ① 接受urlencoded编码
body体中:name=cc&age=18
# print(request.POST)
# ② 接受form-data编码
body体中:分两部分,一部分是数据,一部分是文件
数据部分:name=cc&age=18
# print(request.POST)
文件部分:(二进制数据)
# print(request.FILES)
# ③ 接受json格式
body体中:
{
"name":"cc",
"age":18
}
# 用request.POST取不出来数据,得用request.body
# print(request.body)
return HttpResponse('ok')