Become a sponsor

一个完整的 HTTP 请求在 系统中的处理流程如下:
浏览器
|
| (1) 发起HTTP请求 (携带 Authorization: Bearer <token>)
v
Nginx
|
| (2) 反向代理,静态资源由Nginx处理,API请求转发到Django
v
Django WSGI
|
| (3) 进入中间件链
v
CORS中间件 (corsheaders.middleware.CorsMiddleware)
|
| (4) 处理跨域请求,添加CORS响应头
v
check_login装饰器 (middleware/login_middleware.py)
|
| (5) 验证JWT token有效性
v
URL路由匹配 (application/urls.py)
|
| (6) 根据URL分发到对应视图类
v
PermissionRequired混入类 (middleware/permission_middleware.py)
|
| (7) 验证用户权限节点
v
View视图类 (views.py)
|
| (8) 解析请求参数,调用Service
v
Service服务函数 (services.py)
|
| (9) 执行业务逻辑,操作数据库
v
R.ok()/R.failed() (utils/R.py)
|
| (10) 构造统一JSON响应
v
JsonResponse
|
| (11) 返回响应数据
v
浏览器根据 application/settings.py 的配置,中间件按以下顺序执行:
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware', # 1. CORS跨域处理
'django.middleware.security.SecurityMiddleware', # 2. 安全处理
'django.contrib.sessions.middleware.SessionMiddleware', # 3. Session处理
'django.middleware.common.CommonMiddleware', # 4. 通用处理
# 'django.middleware.csrf.CsrfViewMiddleware', # CSRF已禁用(使用JWT)
'django.contrib.auth.middleware.AuthenticationMiddleware', # 5. 认证处理
'django.contrib.messages.middleware.MessageMiddleware', # 6. 消息处理
'django.middleware.clickjacking.XFrameOptionsMiddleware', # 7. 点击劫持防护
]注意:check_login 和 PermissionRequired 不是 Django 中间件,而是通过装饰器和混入类实现的,作用于视图层面。
# 1. 用户提交用户名密码
POST /login
{
"username": "admin",
"password": "123456",
"captcha": "abc123"
}
# 2. 验证通过后生成JWT Token
from utils.jwt import create_token
payload = {
'userId': user.id,
'username': user.username,
'realname': user.realname
}
token = create_token(payload, timeout=20) # 20分钟过期
# 3. 返回Token给前端
{
"code": 0,
"data": {
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
},
"msg": "登录成功"
}# 1. 前端在请求头中携带Token
headers = {
"Authorization": "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
}
# 2. check_login装饰器验证Token
def check_login(func):
def wrapper(request, *args, **kwargs):
# 忽略不需要认证的URL
ignoreURL = ['/login', '/captcha']
if request.path not in ignoreURL:
# 从请求头获取Token
access_token = request.headers['Authorization']
access_token = access_token.replace('Bearer ', "")
# 验证Token
result = parse_payload(access_token)
if result['code'] != 0:
return R.failed(code=401, msg=result['msg'])
return func(request, *args, **kwargs)
return wrapper# 1. 验证Token时先检查黑名单
def parse_payload(token):
# 检查Token是否在黑名单中
if is_token_blacklisted(token):
return {'code': -1, 'msg': 'token已失效,请重新登录'}
# 解密验证JWT令牌
verified_payload = jwt.decode(token, JWT_SALT, algorithms=[JWT_ALGORITHM])
return {'code': 0, 'data': verified_payload}
# 2. 黑名单检查使用Redis
def is_token_blacklisted(token):
redis = get_redis_connection("default")
fingerprint = hashlib.sha256(token.encode('utf-8')).hexdigest()
key = f'token:blacklist:{fingerprint}'
return redis.exists(key) > 0每个操作对应一个权限节点,格式为 sys:<module>:<action>:
# 示例:案例模块的权限节点
permission_required = ("sys:example:page",) # 分页查询
permission_required = ("sys:example:detail",) # 详情查询
permission_required = ("sys:example:add",) # 添加
permission_required = ("sys:example:update",) # 更新
permission_required = ("sys:example:delete",) # 删除
permission_required = ("sys:example:status",) # 状态更新class PermissionRequired(PermissionRequiredMixin):
def has_permission(self):
# 获取所需权限节点
permissions = self.get_permission_required()
# 获取当前用户ID
user_id = get_user_id(self.request)
# 超级管理员(ID=1)自动放行
if user_id and user_id != 1:
# 获取用户权限列表
permission_list = services.get_user_permissions(user_id)
# 检查是否拥有所需权限
for permission in permissions:
if permission not in permission_list:
return False
return True# application/menu/services.py
def get_user_permissions(user_id):
if user_id == 1:
# 超级管理员拥有所有权限
menu_list = Menu.objects.filter(is_delete=False, type=1, status=0).values()
return [item['permission'] for item in menu_list]
else:
# 普通用户从角色关联中获取权限
sql = '''
SELECT m.* FROM django_menu AS m
INNER JOIN django_role_menu AS rm ON m.id=rm.menu_id
INNER JOIN django_user_role AS ur ON ur.role_id=rm.role_id
WHERE ur.user_id=%s AND (m.type=1 OR (m.type=0 AND m.permission!=''))
AND m.status=0 AND m.is_delete=0
'''
menu_list = Menu.objects.raw(sql, [user_id])
return [item.permission for item in menu_list]以"添加案例"为例,完整的业务处理流程:
1. View层 (ExampleAddView.post)
+-- 检查演示模式 (DJANGO_DEMO)
+-- 调用 Service: services.add_example(request)
2. Service层 (add_example)
+-- 解析请求体: parse_request_body(request)
+-- 表单验证: forms.ExampleForm(data)
+-- 处理文件: save_file(avatar, "example")
+-- 创建记录: Example.objects.create(...)
+-- 返回结果: R.ok(msg="创建成功")
3. Model层 (Example)
+-- Django ORM 生成 SQL
+-- MySQL 执行 INSERT
+-- 自动生成 create_time、update_time所有 API 接口返回统一的 JSON 格式:
{
"code": 0,
"data": {
"id": 1,
"name": "案例名称",
"status": 1
},
"msg": "操作成功",
"ok": true
}{
"code": 0,
"data": {
"records": [
{"id": 1, "name": "案例1"},
{"id": 2, "name": "案例2"}
],
"total": 100,
"size": 10,
"current": 1,
"pages": 10
},
"msg": "操作成功",
"ok": true
}{
"code": 1,
"data": null,
"msg": "操作失败",
"ok": false
}{
"code": 401,
"data": null,
"msg": "token已失效,请重新登录",
"ok": false
}# Service层统一使用 try-except 捕获异常
def add_example(request):
try:
# 业务逻辑
Example.objects.create(...)
return R.ok(msg="创建成功")
except Exception as e:
logging.error(f"添加案例异常: {str(e)}")
return R.failed(msg="添加失败,请稍后重试")# 表单验证失败时返回具体错误信息
form = ExampleForm(data)
if not form.is_valid():
return R.failed(msg=regular.get_err(form))# 数据库操作异常被捕获并返回友好提示
try:
instance.save()
except IntegrityError as e:
return R.failed(msg="数据完整性错误")
except Exception as e:
logging.error(f"数据库异常: {str(e)}")
return R.failed(msg="操作失败,请稍后重试")