六、HttpResponse对象
视图在接收请求并处理后,必须返回HttpResponse对象或子对象。HttpRequest对象由Django创建,HttpResponse对象由开发人员创建。
6.1 HttpResponse
- 可以使用 django.Http.HttpResponse来构造响应对象
HttpResponse(content=响应体, content_type=响应体数据类型,status=状态码 - 也可通过HttpResponse对象属性来设置 响应体、响应体数据类型和状态码
content:表示返回的内容
status_code : 返回的HTTP响应状态码
响应头可以直接将HttpResponse对象当做字典进行响应头键值对的设置
# HttpResponse响应体
def detail8(request, categeory_id, book_id):
"""
HttpResponse只能传递简单的字符串变量,不能传递字典等复杂对象变量
status,相应状态码只能使用系统规定的
content_type:是一个MIME类型,语法形式是:大类/小类
MIME(多用途互联网邮件扩展类型):
七种大类别:video、image、application、text、audio、multipart、message
常见的MIME类型(通用型):
text/html: 超文本标记语言文本 .html
text/xml: xml文档 .xml
text/plain: 普通文本 .txt
text/css
text/javascript
application/json
application/xhtml+xml: XHTML文档 .xhtml
application/rtf: RTF文本 .rtf
application/pdf: PDF文档 .pdf
application/msword: Microsoft Word文件 .word
application/x-gzip: GZIP文件 .gz
application/x-tar: TAR文件 .tar
application/octet-stream: 任意的二进制数据
image/png: PNG图像 .png
image/gif: GIF图形 .gif
image/jpeg: JPEG图形 .jpeg,.jpg
audio/basic: au声音文件 .au
audio/midi,audio/x-midi: MIDI音乐文件 mid,.midi
audio/x-pn-realaudio: RealAudio音乐文件 .ra, .ram
video/mpeg: MPEG文件 .mpg,.mpeg
video/x-msvideo: AVI文件 .avi
"""
return HttpResponse('detail-8', status=400)
6.2 JsonResponse
# JsonResponse
def detail9(request, categeory_id, book_id):
from django.http import JsonResponse
data = {'name': 'zhangsan'}
return JsonResponse(data)
6.3 跳转页面
# 跳转页面
def detail10(request, categeory_id, book_id):
# 跳转到首页,通过reverse反向解析名字,找到首页
path = reverse('book:index')
return redirect(path)
# return redirect('http://www.baidu.com')
七、状态保持
- 浏览器请求服务器是无状态的,无记忆的。
- 无状态:指一次用户请求时,浏览器服务器无法知道之前这个用户做过什么,每次请求都是一次新的请求。
- 无状态原因:浏览器与服务器是使用 Socket套接字进行通信的,服务器将请求结果返回给浏览器之后,会关闭当前的 Socket连接,而且服务器也会在处理页面完毕之后销毁页面对象
- 有时需要保持下来用户浏览的状态,比如用户是否登录过,浏览过哪些商品等
- 实现状态保持主要有两种方式:
在客户端存储信息使用 Cookie
在服务器端存储信息使用 Session
3.7.1 Cookie
3.7.1.1 第一次请求 设置cookie
第一次请求头中没有cookie中
服务器在响应头中设置cookie,浏览器端收到带有 set-cookie 的响应头
# 设置COOKIE
def set_cookie(request):
"""
保存在客户端的数据是Cookie,保存在服务器端的数据是Session
面试官:你是如何理解cookie的?
1、概念
2、流程(大体流程,从http角度分析)
3、开发应用场景
4、你在开发中印象深刻的经历
Cookie:
0、概念:cookie是保存在客户端的数据
cookie是基于域名(IP)的
1、流程
第一次请求过程
① 我们的浏览器第一次请求服务器的时候,不会携带任何 cookie信息
② 服务器接收到请求之后,发现请求中没有任何 cookie信息
③ 服务器设置一个 cookie.这个 cookie设置在响应体中
④ 我们的浏览器接收到这个响应之后,发现响应中有 cookie信息,浏览器会将 cookie信息保存起来
第二次及其之后的过程
⑤ 当我们的浏览器第二次及其之后的请求都会携带 cookie信息
⑥ 我们的服务器接收到请求之后,会发现请求中携带的 cookie信息,这样的话就认识是谁的请求了
2、效果
3、从http协议角度深入掌握cookie的原理
第一次请求过程
①我们是第一次请求服务器,不会携带任何 cookie信息,请求头中没有任何 cookie信息
②服务器会为响应设置 cookie信息,响应头中有set_cookie信息
第二次及其之后的过程
③我们第二次及其之后的请求都会携带 cookie信息,请求头中有 cookie信息
④(可选)在当前我们的代码中,没有再在相应头中设置 cookie,所以响应头中没有set_cookie信息
"""
# 1、先判断有没有cookie信息,先假设没有cookie信息
# 可以通过 if len(request.COOKIES) == 0 判断有没有cookie
# 2、从用户发送的(url)请求体中获取用户名
username = request.GET.get('username')
# 3、因为我们假设没有cookie信息,服务器就要设置cookie信息
response = HttpResponse('set_cookie') # 实例化一个设置cookie的响应对象
response.set_cookie('username', username) # 对响应对象设置cookie
# 4、返回响应
return response
3.7.1.2 第二次请求 得到cookie
第二次及以后的访问,浏览器请求头中携带cookie
服务器端已经知道来访者身份,没有再次 set-cookie ,会话保持建立。
# 获取cookie
def get_cookie(request):
"""
第二次及其之后的过程
⑤ 当我们的浏览器第二次及其之后的请求都会携带 cookie信息
⑥ 我们的服务器接收到请求之后,会发现请求中携带的 cookie信息,这样的话就认识是谁的请求了
"""
# 1、服务器可以接收(查看)cookie信息
cookies = request.COOKIES # cookies就是一个字典
print(cookies) # {'csrftoken': 'jmZfYhlpMMVK9XvRQll8LRGLi3OI4tA6uuGTavAQCoqFym9rl9VnVVvs8OVejLKJ', 'username': 'zhangsan'}
print(type(cookies)) # <class 'dict'>
# 2、得到用户信息就可以继续其他业务逻辑了
username = cookies.get('username')
print(username) # zhangsan
return HttpResponse(username)
3.7.1.3 cookie的生命周期
设置cookie: http://127.0.0.1:8000/set_cookie/?username=zhangsan
max_age,None为默认值,就是浏览器关闭失效。如果设置,单位为秒,3600秒就是1小时。
3.7.1.4 删除cookie的两种办法
- response.delete_cookie(‘username’)
- response.set_cookie(‘username’, username, max_age=0)
设置COOKIE
"""
保存在客户端的数据是Cookie,保存在服务器端的数据是Session
面试官:你是如何理解cookie的?
1、概念
2、流程(大体流程,从http角度分析流程)
3、开发应用场景
4、你在开发中印象深刻的经历
Cookie:
0、概念:cookie是保存在客户端的数据
cookie是基于域名(IP)的
1、流程
第一次请求过程
① 我们的浏览器第一次请求服务器的时候,不会携带任何 cookie信息
② 服务器接收到请求之后,发现请求中没有任何 cookie信息
③ 服务器设置一个 cookie.这个 cookie设置在响应体中
④ 我们的浏览器接收到这个响应之后,发现响应中有 cookie信息,浏览器会将 cookie信息保存起来
第二次及其之后的过程
⑤ 当我们的浏览器第二次及其之后的请求都会携带 cookie信息
⑥ 我们的服务器接收到请求之后,会发现请求中携带的 cookie信息,这样的话就认识是谁的请求了
2、效果
3、从http协议角度深入掌握cookie的原理
第一次请求过程
①我们是第一次请求服务器,不会携带任何 cookie信息,请求头中没有任何 cookie信息
②服务器会为响应设置 cookie信息,响应头中有set_cookie信息
第二次及其之后的过程
③我们第二次及其之后的请求都会携带 cookie信息,请求头中有 cookie信息
④(可选)在当前我们的代码中,没有再在相应头中设置 cookie,所以响应头中没有set_cookie信息
"""
# http://127.0.0.1:8000/set_cookie/?username=zhangsan
# 1、先判断有没有cookie信息,先假设没有cookie信息
# 可以通过 if len(request.COOKIES) == 0 判断有没有cookie
# 2、从用户发送的(url)请求体中获取用户名
username = request.GET.get('username')
# 3、因为我们假设没有cookie信息,服务器就要设置cookie信息
response = HttpResponse('set_cookie') # 实例化一个设置cookie的响应对象
# max_age,None为默认值,就是浏览器关闭失效。如果设置,单位为秒,3600秒就是1小时。
response.set_cookie('username', username, max_age=3600) # 对响应对象设置cookie
# 删除cookie的两种方法
# response.delete_cookie('username')
# response.set_cookie('username', username, max_age=0)
4、返回响应
return response
3.7.2 Session
保存在客户端的数据是Cookie,保存在服务器端的数据是Session,session需要依赖于cookie,如果浏览器禁用了cookie,则session也不能实现。
保存在客户端的数据是Cookie,
保存在服务器端的数据是Session,session需要依赖于cookie,
如果浏览器禁用了cookie,则session也不能实现
面试官:
问题1、换了浏览器还能获取session吗?
正常不可以,session依赖于cookie,换了浏览器cookie中就没有sessionid了。
如果想可以,需要提取原来cookie中的sessionid,手工携带
问题2、不换浏览器,删除sessionid,服务器还能获取吗?
不能
问题3、从新执行set_session,会重新生成sessionid吗?
能
session:
0、概念
1、流程
第一次请求:
① 浏览器第一次请求的时候可以携带一些信息(用户名/密码),此时cookie中没有任何信息。
② 当服务器接收到这个请求之后进行用户名和密码的验证,验证没有问题可以设置 session信息
③ 在 session设置信息的同时(session信息保存在服务器端).服务器会在响应头中设置一个sessionid,置入cookie中
④ 客户端(浏览器)在接收到响应之后,会将 cookie信息保存起来(其中包含了sessionid的信息)
第二次及其之后的请求:
⑤ 第二次及其之后浏览器的请求都会携带这个包含 sessionid 的 cookie 信息
⑥ 当服务器接收到这个请求之后,会获取到 sessionid 信息,然后进行验证, 验证成功,
则可以根据 sessionid 读取服务器本地的 session信息(session信息保存在服务器端)
2、效果
3、从原理(http)角度
第一次请求:
①第一次请求,在请求头中没有携任何 cookie信息
②我们 session在设置的时候, session会做2件事
#第一件:将生成的session保存在django_session表中,
#第二件:在响应头中设置cookie信息set_cookie,把sessionid置入其中,这个 cookie信息是以 sessionidkey为 value为xxxx
cookie肯定会以响应的形式在相应头中出现
第二次及其之后的:
③都会携带 cookie信息,特别是 sessionid
4、在django中,settings.py的 INSTALLED_APPS = [‘django.contrib.sessions’,]设置了session,
执行迁移后会在数据库中生成一个django_session的数据表,包含三个字段:session_key、session_data、session_date
分别表示sessionid,session数据和session失效期
3.7.2.0 session 操作
通过 HttpRequest对象的session属性进行会话的读写操作。
- 1)以键值对的格式写session
request. session[‘键’]=值 - 2)根据键读取值
request. session.get(‘键’, 默认值) - 3)清除所有session,在存储中删除值部分
request. session. clear() - 4)清除session数据,在存储中删除 session的整条数据
request. session. flush() - 5)删除session中的指定键及值,在存储中只删除某个键及对应的值
del request. session[‘键’] - 6)设置session的有效
request. session. set_expiry(value)
如果 value是一个整数, session在value秒没有活动后过期
如果 value为o,那么用户 session的Cookie将在用户的浏览器关闭时过期
如果 value为one那么 session有效期将采用系统默认值,默认为两周,可以通过在 settings py中设置 SESSION_COOKIE_AGE来设置全局默认值
3.7.2.1 设置session
def set_session(request):
# 先清除浏览器的所有cookie
# http://127.0.0.1:8000/set_session/?username=zhangsan&password=123
# 1、第一次请求,没有cookie信息
print(request.COOKIES) # {}
# 2、对用户名密码进行验证,假设验证成功,设置用户id
user_id = 6666
# 3、设置session信息,request.session可以理解为字典,sessionid是服务器自己设置的,不是我们设置的
# 设置session时,服务器自动做了两件事
# ① 将生成的session保存在django_session表中,
# ② 在响应头中设置cookie信息set_cookie,把sessionid置入其中
# 如果服务器检测到request.COOKIES中有sessionid,就不会重新生成sessionid,只会对数据重新赋值
request.session['user_id'] = user_id
print(request.session)
return HttpResponse('set_session')
第一次请求中没有cookie信息
第一次响应中有set_cookie信息,其中包含sessionid信息
浏览器信息显示
3.7.2.2 获取session
def get_session(request):
# http://127.0.0.1:8000/get_session/
# 1、第二次及以后请求,携带cookie信息
print(request.COOKIES) # {'sessionid': 'gohtkpyyrlgntxm3ek7fvrqqh6dkcaz7'}
# 2、服务器获取sessionid,进行验证,验证成功会获取session信息
user_id = request.session['user_id']
print(user_id) # 6666
# 可以处理业务逻辑
return HttpResponse('get_session')
八、类视图与中间件
8.1 类视图
类视图是采用面向对象的思路
1、定义类视图
① 继承自django.views的View。
② 不同的请求方式有不同的业务逻辑.类视图的方法就直接采用http请求名字作为函数名,如,get,post,put,patch,delete,head,options,trace等。
③ 类视图的第一个参数固定为self,第二个参数必须是请求实例对象。类视图的方法,必须有返回值,返回值是HttpResponse及其子类。
2、类视图的url引导
① url第一个参数是正则,login/。
② 第二个参数是个视图函数名 LoginView.as_view()
from django.views import View
class LoginView(View):
def get(self, request):
return HttpResponse('get')
def post(self, request):
return HttpResponse('post')
def put(self, request):
return HttpResponse('put')
def OOOO(self, request):
return HttpResponse('OOOO')
8.2 多继承
"""
业务需求:
个人中心页面 -- 必须登录才能显示
GET 展示个人中心
POST 实现个人中心信息的修改
"""
from django.contrib.auth.mixins import LoginRequiredMixin
class CenterView(LoginRequiredMixin, View):
"""
两个父类按MRO的顺序,也可以理解为业务流程
登录个人中心首先需要验证是否登录,django的LoginRequireMixin封装好了验证方法
如果检测到没有登录,会自动跳转到 http://127.0.0.1:8000/accounts/login/?next=/center/
"""
def get(self, request):
return HttpResponse('个人中心展示')
def post(self, request):
return HttpResponse('个人信息修改')
8.3 中间件
伴随请求和响应的过程中发生的事情(函数)。
Django中的中间件是一个轻量级底层的插件系统,可以介入 Django的请求和响应处理过程,修改Django的输入或输出。中间件的设计为开发者提供了一种无侵入式的开发方式,增强了 Django框架的健壮性。
我们可以使用中间件,在 Django处理视图的不同阶段对输入或输出进行干预
中间件文档:https://docs.djangoproject.com/en/3.2/topics/http/middleware/
8.3.1中间件的定义方法
定义一个中间件工厂函数,然后返回一个可以被调用的中间件。
中间件工厂函数需要接收一个可以调用的 get_response对象
返回的中间件也是一个可以被用的对象,并且像视图一样需要接收一个 request对象参数,返回一个 response对象。
8.3.2 多个中间件的执行顺序
请求前:按注册顺序执行
请求后/响应后:与注册顺序相反
8.3.3 中间件的初始化
# -*- encoding: utf-8 -*-
"""
中间件的作用:每次请求和响应的时候都会调用
中间件的定义:嵌套视图函数
中间件的注册:在settings.py的MIDDLEWARE=[]列表中添加 'book.middleware.simple_middleware',
中间件的使用举例:可以判断每次请求中是否携带了cookie的某些信息
"""
from django.http import HttpResponse
def simple_middleware(get_response):
# 这里是中间件第一次调用执行的地方,程序启动,首次发送请求会执行一次,以后的请求不会执行
print('init___middleware')
def middleware(request):
# 这里是请求前
print('before request')
username = request.COOKIES.get('username')
if username is None:
print('usename is None!')
# return HttpResponse('亲,你没有登录啊!')
else:
print(username)
response = get_response(request)
# 这里是响应后/请求后
print('after response/request')
return response
return middleware