目录
Cookies
Django 中 Cookie 的语法
Session(保存在服务端的键值对)
工作原理
实例
二 Django中间件
自定义中间件
自定义中间件类的方法
process_request 方法
process_response
process_view
process_exception
三 Django Nginx+uwsgi 安装配置
Cookie 是存储在客户端计算机上的文本文件,并保留了各种跟踪信息。
识别返回用户包括三个步骤:
HTTP 是一种"无状态"协议,这意味着每次客户端检索网页时,客户端打开一个单独的连接到 Web 服务器,服务器会自动不保留之前客户端请求的任何记录。
但是仍然有以下三种方式来维持 Web 客户端和 Web 服务器之间的 session 会话:
一个 Web 服务器可以分配一个唯一的 session 会话 ID 作为每个 Web 客户端的 cookie,对于客户端的后续请求可以使用接收到的 cookie 来识别。
在Web开发中,使用 session 来完成会话跟踪,session 底层依赖 Cookie 技术。
设置 cookie:
rep.set_cookie(key,value,...) rep.set_signed_cookie(key,value,salt='加密盐',...)
获取 cookie:
request.COOKIES.get(key)
删除 cookie:
rep =HttpResponse || render || redirect rep.delete_cookie(key)
创建应用和模型
models.py
class UserInfo(models.Model):username = models.CharField(max_length=32)password = models.CharField(max_length=64)
urls.py
from django.contrib import admin
from django.urls import path
from cookie import views
urlpatterns = [path('admin/', admin.site.urls),path('login/', views.login),path('index/', views.index),path('logout/', views.logout),path('order/', views.order)
views.py
def login(request):if request.method == "GET":return render(request, "login.html")username = request.POST.get("username")password = request.POST.get("pwd")user_obj = models.UserInfo.objects.filter(username=username, password=password).first()print(user_obj.username)if not user_obj:return redirect("/login/")else:rep = redirect("/index/")rep.set_cookie("is_login", True)return repdef index(request):print(request.COOKIES.get('is_login'))status = request.COOKIES.get('is_login') # 收到浏览器的再次请求,判断浏览器携带的cookie是不是登录成功的时候响应的 cookieif not status:return redirect('/login/')return render(request, "index.html")def logout(request):rep = redirect('/login/')rep.delete_cookie("is_login")return rep # 点击注销后执行,删除cookie,不再保存用户状态,并弹到登录页面def order(request):print(request.COOKIES.get('is_login'))status = request.COOKIES.get('is_login')if not status:return redirect('/login/')return render(request, "order.html")
以下创建三个模板文件:login.html、index.html、order.html。
login.html
Title
用户登录
index.html
Title
index 页面。。。
注销
order.html
Title
order 页面。。。
注销
运行结果如下图所示:
服务器在运行时可以为每一个用户的浏览器创建一个其独享的 session 对象,由于 session 为用户浏览器独享,所以用户在访问服务器的 web 资源时,可以把各自的数据放在各自的 session 中,当用户再去访问该服务器中的其它 web 资源时,其它 web 资源再从用户各自的 session 中取出数据为用户服务。
a. 浏览器第一次请求获取登录页面 login。
b. 浏览器输入账号密码第二次请求,若输入正确,服务器响应浏览器一个 index 页面和一个键为 sessionid,值为随机字符串的 cookie,即 set_cookie ("sessionid",随机字符串)。
c. 服务器内部在 django.session 表中记录一条数据。
django.session 表中有三个字段。
d. 浏览器第三次请求其他资源时,携带 cookie :{sessionid:随机字符串},服务器从 django.session 表中根据该随机字符串取出该用户的数据,供其使用(即保存状态)。
注意: django.session 表中保存的是浏览器的信息,而不是每一个用户的信息。 因此, 同一浏览器多个用户请求只保存一条记录(后面覆盖前面),多个浏览器请求才保存多条记录。
cookie 弥补了 http 无状态的不足,让服务器知道来的人是"谁",但是 cookie 以文本的形式保存在浏览器端,安全性较差,且最大只支持 4096 字节,所以只通过 cookie 识别不同的用户,然后,在对应的 session 里保存私密的信息以及超过 4096 字节的文本。
session 设置:
request.session["key"] = value
执行步骤:
session 获取:
request.session.get('key')
删除 session_data 里的其中一组键值对:
del request.session["key"]
执行步骤:
创建路由:
urls.py
from session import views as session_viewsurlpatterns = [path('session_login/', session_views.login),path('s_index/', session_views.s_index),path('s_logout/', session_views.s_logout),
]
创建视图函数:
views.py
def login(request):if request.method == "GET":return render(request, "login.html")username = request.POST.get("username")password = request.POST.get("pwd")user_obj = models.UserInfo.objects.filter(username=username, password=password).first()print(user_obj.username)if not user_obj:return redirect("/session_login/")else:request.session['is_login'] = Truerequest.session['user1'] = usernamereturn redirect("/s_index/")def s_index(request):status = request.session.get('is_login')if not status:return redirect('/session_login/')return render(request, "s_index.html")def s_logout(request):# del request.session["is_login"] # 删除session_data里的一组键值对request.session.flush() # 删除一条记录包括(session_key session_data expire_date)三个字段return redirect('/session_login/')
模板文件:
s_index.html
Title
session_index 页面。。。{{ request.session.user1 }}
注销
运行结果如下图所示
Django 中间件是修改 Django request 或者 response 对象的钩子,可以理解为是介于 HttpRequest 与 HttpResponse 处理之间的一道处理过程。
浏览器从请求到响应的过程中,Django 需要通过很多中间件来处理,可以看如下图所示:
Django 中间件作用:
中间件组件配置在 settings.py 文件的 MIDDLEWARE 选项列表中。
配置中的每个字符串选项都是一个类,也就是一个中间件。
Django 默认的中间件配置:
中间件可以定义四个方法,分别是:
process_request(self,request)
process_view(self, request, view_func, view_args, view_kwargs)
process_exception(self, request, exception)
process_response(self, request, response)
自定义中间的步骤:
在 app 目录下新建一个 py 文件,名字自定义,并在该 py 文件中导入 MiddlewareMixin:
from django.utils.deprecation import MiddlewareMixin
自定义的中间件类,要继承父类 MiddlewareMixin:
class MD1(MiddlewareMixin): pass
在 settings.py 中的 MIDDLEWARE 里注册自定义的中间件类:
自定义中间件类的方法有:process_request 和 process_response。
process_request 方法有一个参数 request,这个 request 和视图函数中的 request 是一样的。
process_request 方法的返回值可以是 None 也可以是 HttpResponse 对象。
process_request 方法是在视图函数之前执行的。
当配置多个中间件时,会按照 MIDDLEWARE中 的注册顺序,也就是列表的索引值,顺序执行。
不同中间件之间传递的 request 参数都是同一个请求对象。
实例
from django.utils.deprecation import MiddlewareMixinfrom django.shortcuts import render, HttpResponseclass MD1(MiddlewareMixin):def process_request(self, request):print("md1 process_request 方法。", id(request)) #在视图之前执行
process_response 方法有两个参数,一个是 request,一个是 response,request 是请求对象,response 是视图函数返回的 HttpResponse 对象,该方法必须要有返回值,且必须是response。
process_response 方法是在视图函数之后执行的。
当配置多个中间件时,会按照 MIDDLEWARE 中的注册顺序,也就是列表的索引值,倒序执行。
实例
class MD1(MiddlewareMixin):def process_request(self, request):print("md1 process_request 方法。", id(request)) #在视图之前执行def process_response(self,request, response): :#基于请求响应print("md1 process_response 方法!", id(request)) #在视图之后return response
从下图看,正常的情况下按照绿色的路线进行执行,假设中间件1有返回值,则按照红色的路线走,直接执行该类下的 process_response 方法返回,后面的其他中间件就不会执行。
process_view 方法格式如下:
process_view(request, view_func, view_args, view_kwargs)
process_view 方法有四个参数:
view_args 和 view_kwargs 都不包含第一个视图参数(request)。
process_view 方法是在视图函数之前,process_request 方法之后执行的。
返回值可以是 None、view_func(request) 或 HttpResponse 对象。
当最后一个中间件的 process_request 到达路由关系映射之后,返回到第一个中间件 process_view,然后依次往下,到达视图函数。
实例 class MD1(MiddlewareMixin):def process_request(self, request):print("md1 process_request 方法。", id(request)) #在视图之前执行def process_response(self,request, response): :#基于请求响应print("md1 process_response 方法!", id(request)) #在视图之后return responsedef process_view(self,request, view_func, view_args, view_kwargs):print("md1 process_view 方法!") #在视图之前执行 顺序执行#return view_func(request)
process_exception 方法如下:
process_exception(request, exception)
参数说明:
process_exception 方法只有在视图函数中出现异常了才执行,按照 settings 的注册倒序执行。
在视图函数之后,在 process_response 方法之前执行。
process_exception 方法的返回值可以是一个 None 也可以是一个 HttpResponse 对象。
返回值是 None,页面会报 500 状态码错误,视图函数不会执行。
process_exception 方法倒序执行,然后再倒序执行 process_response 方法。
返回值是 HttpResponse 对象,页面不会报错,返回状态码为 200。
视图函数不执行,该中间件后续的 process_exception 方法也不执行,直接从最后一个中间件的 process_response 方法倒序开始执行。
若是 process_view 方法返回视图函数,提前执行了视图函数,且视图函数报错,则无论 process_exception 方法的返回值是什么,页面都会报错, 且视图函数和 process_exception 方法都不执行。
直接从最后一个中间件的 process_response 方法开始倒序执行:
实例
class MD1(MiddlewareMixin):def process_request(self, request):print("md1 process_request 方法。", id(request)) #在视图之前执行def process_response(self,request, response): :#基于请求响应print("md1 process_response 方法!", id(request)) #在视图之后return responsedef process_view(self,request, view_func, view_args, view_kwargs):print("md1 process_view 方法!") #在视图之前执行 顺序执行#return view_func(request)def process_exception(self, request, exception):#引发错误 才会触发这个方法print("md1 process_exception 方法!")# return HttpResponse(exception) #返回错误信息
Django Nginx+uwsgi 安装配置 | 菜鸟教程 (runoob.com)