1. Django生命周期
django的生命周期是:前端请求—>nginx—>uwsgi.—>中间件—>url路由---->view视图—>orm---->拿到数据返回给view---->视图将数据渲染到模版中拿到字符串---->中间件—>uwsgi---->nginx---->前端渲染。
2. Django中间件
Django 中间件是修改 Django request 或者 response 对象的钩子,可以理解为是介于 HttpRequest 与 HttpResponse 处理之间的一道处理过程。
浏览器从请求到响应的过程中,Django 需要通过很多中间件来处理,可以看如下图所示:
2.1 内置中间件
- django.middleware.security.SecurityMiddleware
做了一些安全处理的中间件。比如设置防御的请求头,比如做了http协议转为https协议的工作等。
- django.contrib.sessions.middleware.SessionMiddleware
session中间件。会给request添加一个处理好的session对象。
- django.middleware.common.CommonMiddleware
通用中间件,会处理一些URL,比如baidu.com会自动的处理成www.baidu.com。比如/blog/111会处理成/blog/111/自动加上反斜杠。
- django.middleware.csrf.CsrfViewMiddleware
保护中间件,在提交表单的时候会必须加入csrf_token,cookie中也会生成一个名叫csrftoken的值,也会在header中加入一个HTTP_X_CSRFTOKEN的值来放置CSRF攻击。SessionMiddleware必须出现在CsrfMiddleware之前。
- django.contrib.auth.middleware.AuthenticationMiddleware
用户授权中间件。会给request添加一个user对象的中间件。该中间件必须在sessionmiddleware后面。
- django.contrib.messages.middleware.MessageMiddleware
消息处理中间件。为了在多个模板中可以使用我们返回给模板的变量,并且简化操作。
- django.middleware.clickjacking.XFrameOptionsMiddleware
防止通过浏览器页面跨Frame出现clickjacking(欺骗点击)攻击出现。
中间件组件配置在 settings.py 文件的 MIDDLEWARE 选项列表中,配置中的每个字符串选项都是一个类,也就是一个中间件。Django 默认的中间件配置如下:
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]
2.2 自定义中间件
中间件可以定义五个方法,分别是:
process_request(self,request)
process_view(self, request, view_func, view_args, view_kwargs)
process_template_response(self,request,response)
process_exception(self, request, exception)
process_response(self, request, response)
常用的是process_request和process_response,在自己定义中间件时,必须继承MiddlewareMixin,自定义中间件步骤如下:
①在应用(app1)下创建myMiddleWare.py文件,定义中间件类;
#文件名:myMiddleWare.py
from django.utils.deprecation import MiddlewareMixin
class thCheck(MiddlewareMixin):
def process_request(self, request):
print(8848)
def process_response(self, request, response):
print(9999)
return response
②注册自定义中间件;
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
"app1.myMiddleWare.thCheck", # 自定义的中间件
]
③在app1.views.py中定义视图函数index:
#文件名:app1.views.py
from django.shortcuts import render
from django.http import HttpResponse
from app1.models import Test
# Create your views here.
# 用作测试的视图函数
def index(request):
print("执行index视图函数...")
return HttpResponse("index")
def function1(request):
t = Test(name="func1", age=8)
t.save()
return HttpResponse("function1")
def function2(request):
t = Test(name="func2", age=4)
t.save()
return HttpResponse("function2")
④测试:在浏览器中访问http://127.0.0.1:8000/api/app1/index,终端打印如下信息:
3. 典型应用案例
①限制访问频率(每分钟最多访问10次)
②验证是否登录(未登录用户转到login界面)
3.1 定义中间件
为了实现限制访问频率和验证登录两个功能,分别定义中间件AccessFrequencyMiddleware和LoginRequireMiddleware:
文件名:app1.myMiddleWare.py
import time
from django.http import HttpResponse, JsonResponse, HttpResponseRedirect
from django.utils.deprecation import MiddlewareMixin
from django.urls import reverse
class User(object):
def __init__(self, ip):
self.ip = ip
self.reset()
def reset(self):
self.first_time = time.time()
self.counter = 1
# {ip:User()}
user_dict = {}
class AccessFrequencyMiddleware(MiddlewareMixin):
def process_request(self, request):
remote_ip = request.META.get('REMOTE_ADDR')
if remote_ip not in user_dict:
# 用户首次访问
user_dict[remote_ip] = User(remote_ip)
else:
user = user_dict.get(remote_ip)
time_interval = time.time() - user.first_time
user.counter += 1
if time_interval < 60 and user.counter > 10:
user.last_time = time.time()
user.is_forbidden = True
return HttpResponse('访问频率过高,限制访问')
elif time_interval > 60:
user.reset()
else:
pass
class LoginRequireMiddleware(MiddlewareMixin):
def __init__(self, get_response=None):
super().__init__(get_response)
self.get_response = get_response
self.white_list = ["/login/", "/register/"] # 白名单
self.black_list = [] # 黑名单
def process_request(self, request):
path = request.path
print(path, request.user.is_authenticated)
if request.user.is_authenticated or path in self.white_list:
return None
elif path in self.black_list:
return JsonResponse({"code": 0, "error": "禁止访问"}, status=403)
else:
# viewname 可以是在path()中定义的路由别名name,通过reverse(viewname)函数可以反向查找URL
return HttpResponseRedirect(reverse('login-view'))
3.2 注册自定义中间件
文件名:django_study.settings.py
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
"app1.myMiddleWare.AccessFrequencyMiddleware",
"app1.myMiddleWare.LoginRequireMiddleware",
]
3.3 定义登录视图函数
在django_study工程路径下添加views.py程序,编写登录视图函数:
文件名:django_study.views.py
from django.http import HttpResponse
def login(request):
print("请登录...")
return HttpResponse("登录界面")
3.3 注册视图函数对应的URL
文件名:django_study.urls.py
from django.contrib import admin
from django.urls import path
from django.conf.urls import include
import app1.urls as app1_urls
import app2.urls as app2_urls
from .views import *
urlpatterns = [
path("admin/", admin.site.urls),
path("login/", login, name="login-view"), #视图函数URL
path("api/app1/", include(app1_urls)),
path("api/app2/", include(app2_urls)),
]
3.4 测试
略
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。