Python Django Ninja 框架 snake-case蛇形 转换 camel-case 驼峰
方案一:定义 Schema 进行转换
在 Django Ninja 中,可以实现自动转换,不需要手动重命名每个字段。以下是具体实现方式:
自动转换方案(基于您现有代码)
▼python复制代码from ninja import Schema from pydantic import Field from pydantic.alias_generators import to_camel from typing import Optional class CamelModel(Schema): class Config: alias_generator = to_camel # 自动snake_case -> camelCase populate_by_name = True # 允许通过别名访问 class UserLoginResponse(CamelModel): # 继承自CamelModel # 保持原有字段名(snake_case),会自动转为camelCase user_account: str user_name: str user_id: int avatar_url: Optional[str] = None # ...其他字段保持原样...
关键点说明
alias_generator = to_camel:自动将 snake_case 转为 camelCasepopulate_by_name = True:允许通过原始字段名访问- 无需修改现有代码:
- 服务层继续返回
user_account等 snake_case 字段 - 前端将收到
userAccount等 camelCase 字段
效果验证
▼python复制代码# 测试输出 response = UserLoginResponse( user_account="test", user_name="Test User", user_id=1 ) print(response.json()) # 输出: {"userAccount":"test","userName":"Test User","userId":1}
这样既保持了后端代码的 Python 风格,又满足了前端 JavaScript 的命名习惯
保险起见的写法
1. 自动转换已足够的情况
▼python复制代码class UserLoginResponse(CamelModel): user_account: str # 会自动转为 userAccount # ...其他字段...
- 足够:如果所有字段都遵循
snake_case命名规范 - 自动转换:
alias_generator = to_camel会处理大多数情况
2. 需要显式 Field 的情况
▼python复制代码class UserLoginResponse(CamelModel): user_account: str = Field(alias="userAccount") # 显式指定 # ...其他字段...
- 特殊字段:当字段名不符合常规转换规则时
- 文档清晰:让 API 文档明确显示前端应该使用的字段名
- 前后端约定:确保即使未来修改转换逻辑,该字段名保持不变
!!! 但是这种定义 不能对 request 起到效果
因为,在 ninja 项目源码中的schema.py 下的 DjangoGetter class中的 def __getattr__(self, key: str) -> Any 函数,你会发现,框架,是先对request 中的 keys 和 schemas 的 keys 进行比对,保证数据符合要求再进行,对应的to_snake的转换,而不是先转换,request key 的格式,所以就会发生报错,
解决方式有用显示 Field ,alias 去处理如上方写法,定义每一个 字段,的 camel case ,这样 函数 会优先使用 alias 的字段,对比就不会出错
▼python复制代码class UserLoginRequest(RequestBase): user_account: str = Field(..., alias="userAccount") user_password: str = Field(..., alias="userPassword")
方案二,写个中间件,对所有请求进行字体转换
1. 这种也是解决,上面,省去对请求,每个字段进行表明写法的方法,创建中间件文件
推荐位置
▼plain复制代码your_project/ ├── middleware/ # 新建目录存放中间件 │ ├── __init__.py │ └── camel_case.py # 驼峰转蛇形中间件 ├── api.py # Django Ninja 的 api 实例 └── settings.py
middleware/camel_case.py 内容
▼python复制代码import json import re from django.utils.text import camel_case_to_spaces, slugify from django.http import HttpRequest def camel_to_snake(data): """递归将字典的键从 camelCase 转为 snake_case""" if isinstance(data, dict): return { # 转换逻辑:camelCase → snake_case slugify(camel_case_to_spaces(key)).replace("-", "_"): camel_to_snake(value) for key, value in data.items() } elif isinstance(data, list): return [camel_to_snake(item) for item in data] return data class CamelCaseMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request: HttpRequest): # 只处理 JSON 请求(避免影响表单/文件上传等) if request.content_type == "application/json" and request.body: try: data = json.loads(request.body) # 修改请求体数据 request._body = json.dumps(camel_to_snake(data)).encode("utf-8") except json.JSONDecodeError: pass return self.get_response(request)
2. 注册中间件到 Django Ninja
在 api.py 中注册
▼python复制代码from ninja import NinjaAPI from .middleware.camel_case import CamelCaseMiddleware api = NinjaAPI() api.add_middleware(CamelCaseMiddleware) # 关键!添加中间件
3. 确保中间件能被导入
在 middleware/__init__.py 中暴露中间件
▼python复制代码from .camel_case import CamelCaseMiddleware __all__ = ["CamelCaseMiddleware"]
4. (可选)添加到 Django 全局中间件
如果希望中间件 对所有请求(包括非 API 请求)生效,可以在 settings.py 中添加:
▼python复制代码# settings.py MIDDLEWARE = [ ..., 'your_project.middleware.CamelCaseMiddleware', # 全局中间件 ]
但 不建议这样做,因为:
- 可能影响 Django Admin、静态文件等非 API 请求。
- Django Ninja 的
api.add_middleware()是更精准的注册方式。
5. 测试中间件
发送请求
▼bash复制代码curl -X POST http://localhost:8000/api/user \ -H "Content-Type: application/json" \ -d '{"userName":"John", "userAge":25}'
后端接收的数据
▼python复制代码# 自动转换为: {"user_name": "John", "user_age": 25}
关键注意事项
- 中间件顺序
Django Ninja 的中间件按注册顺序执行,确保转换中间件在认证中间件之前。 - 性能影响
对每个 JSON 请求会进行递归转换,高频 API 可能需要优化。 - 异常处理
中间件中捕获了JSONDecodeError,避免非法 JSON 导致崩溃。 - Content-Type 检查
仅处理application/json请求,避免影响文件上传等场景。
替代方案对比
| 方案 | 优点 | 缺点 |
|---|---|---|
| 中间件 | 全局生效,无需改 Schema | 需要处理递归转换逻辑 |
| Pydantic 别名 | 声明式配置,代码更干净 | 每个 Schema 需单独设置 |
| 手动转换 | 灵活控制 | 代码冗余,维护成本高 |
推荐优先使用 中间件 或 Pydantic 别名,根据项目规模选择。
评论
问答助学
相关内容
0个评论
全部评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
