You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
iTi-Flask/.cursor/rules/framework.mdc

596 lines
13 KiB
Plaintext

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

---
alwaysApply: true
---
# 后端项目开发规范 (Flask + APIFlask)
## 项目架构
本项目基于 **Flask + APIFlask** 框架,使用以下技术栈:
- **Web框架**: Flask + APIFlask (API文档自动生成)
- **ORM**: SQLAlchemy
- **数据库迁移**: Flask-Migrate (Alembic)
- **认证**: Flask-JWT-Extended
- **序列化**: Marshmallow
- **限流**: Flask-Limiter
- **缓存**: Flask-Caching
- **事件系统**: 自定义事件总线
参考文件:
- @file:iti/app.py
- @file:iti/applications/__init__.py
- @file:iti/config.py
## 项目结构
```
iti/applications/
├── __init__.py # 应用工厂函数
├── common/ # 公共模块
│ ├── crud.py # CRUD 基础操作
│ ├── enums.py # 枚举定义
│ ├── exceptions/ # 异常定义
│ ├── utils/ # 工具函数
│ └── storage/ # 文件存储
├── models/ # 数据模型
│ ├── schema/ # Schema 定义
│ └── *.py # 模型文件
├── routes/ # 路由定义
│ ├── sys/ # 系统管理路由
│ └── schemas/ # 请求/响应 Schema
├── service/ # 业务逻辑层
├── extensions/ # 扩展初始化
└── events/ # 事件处理器
```
## 代码规范
### 1. 应用工厂模式
使用应用工厂函数创建 Flask 应用:
```python
from iti.applications import create_app
app = create_app(config_name='dev')
```
参考:
- @file:iti/applications/__init__.py
### 2. 配置管理规范
#### 配置类继承结构
```python
class BaseConfig:
"""基础配置类 - 所有环境共享的配置"""
# 基础配置项
class DevConfig(BaseConfig):
"""开发环境配置"""
DEBUG = True
class ProdConfig(BaseConfig):
"""生产环境配置"""
DEBUG = False
```
#### 环境变量加载
- 使用 `python-dotenv` 加载 `.env` 文件
- 优先级:`.env.local` > `.env.{FLASK_ENV}` > `.env`
- 敏感配置必须使用环境变量
参考:
- @file:iti/config.py
### 3. 数据模型规范
#### 模型基类
所有模型继承 `BaseModelMixin`
```python
from iti.applications.common.crud import BaseModelMixin
from iti.applications.extensions import db
class User(BaseModelMixin):
__tablename__ = "sys_user"
username = db.Column(db.String(64), nullable=False, comment="用户名")
# 其他字段...
```
**BaseModelMixin 包含**:
- `id`: UUID 主键(自动生成)
- `created_at`: 创建时间
- `updated_at`: 更新时间
- `created_by`: 创建人
- `updated_by`: 更新人
- `remark`: 备注
参考:
- @file:iti/applications/common/crud.py
- @file:iti/applications/models/sys_user.py
#### 模型关系定义
```python
# 多对多关系
roles = db.relationship(
"Role",
secondary="sys_user_role",
back_populates="users",
)
# 一对多关系
children = db.relationship(
"SysDept",
backref="parent",
lazy="dynamic",
)
```
### 4. Schema 序列化规范
#### Schema 定义
使用 Marshmallow Schema 进行序列化/反序列化:
```python
from iti.applications.common.utils import BaseSchema
from apiflask.fields import String, DateTime, Enum, Nested
class UserSchema(BaseSchema):
id = String()
username = String()
created_at = DateTime(data_key="createdAt", format="%Y-%m-%d %H:%M:%S")
# 关系字段
roles = Nested("RoleSchema", many=True, dump_only=True)
```
**命名规范**:
- 响应字段使用 camelCase通过 `data_key` 转换)
- 时间字段格式:`%Y-%m-%d %H:%M:%S`
参考:
- @file:iti/applications/models/sys_user.py
### 5. 路由定义规范
#### Blueprint 创建
使用 APIFlask 的 APIBlueprint
```python
from apiflask import APIBlueprint
from iti.applications.common.utils import success
from iti.applications.extensions import db
bp = APIBlueprint("module_name", __name__, url_prefix="/api/xxx", tag="模块.子模块")
```
#### 路由装饰器
```python
@bp.post("/create")
@bp.input(CreateRequest.Schema, location="json")
@bp.output(ResponseSchema)
@jwt_required()
@sys_log(name="创建", desc="创建xxx", type=LogType.OPERATION)
def create(json_data: CreateRequest):
"""创建资源"""
# 业务逻辑
return success(data, message="创建成功")
```
**装饰器顺序**:
1. `@bp.method("/path")` - 路由定义
2. `@bp.input()` - 请求验证
3. `@bp.output()` - 响应定义
4. `@jwt_required()` - 认证
5. `@sys_log()` - 日志记录
6. `@limiter.limit()` - 限流(如需要)
参考:
- @file:iti/applications/routes/sys/auth.py
- @file:iti/applications/routes/__init__.py
### 6. 请求/响应 Schema 规范
#### 请求 Schema
```python
from apiflask.fields import String, Integer
from marshmallow import validate
class CreateRequest(ma.Schema):
username = String(
required=True,
validate=validate.Length(min=3, max=64),
metadata={"description": "用户名"}
)
email = String(
validate=validate.Email(),
metadata={"description": "邮箱"}
)
```
#### 响应 Schema
使用模型 Schema 或自定义 Schema
```python
@bp.output(UserSchema)
# 或
@bp.output(ma.Schema)
```
### 7. 业务逻辑层规范
#### Service 层职责
- 复杂的业务逻辑处理
- 跨模型的操作
- 缓存逻辑
- 外部服务调用
#### Service 文件组织
```python
# service/sys_user.py
from iti.applications.models import User
from iti.applications.extensions import db
def get_user_by_id(user_id: str) -> User:
"""根据ID获取用户"""
return db.session.scalar(select(User).filter_by(id=user_id))
def create_user(data: dict) -> User:
"""创建用户"""
user = User(**data)
db.session.add(user)
db.session.commit()
return user
```
参考:
- @file:iti/applications/service/sys_config.py
### 8. 异常处理规范
#### 业务异常
使用 `BizException` 抛出业务异常:
```python
from iti.applications.common.exceptions.biz_exp import BizException
if user is None:
raise BizException("用户不存在")
```
#### 异常响应格式
异常会自动转换为 JSON 响应:
```json
{
"code": 400,
"message": "用户不存在",
"detail": {}
}
```
参考:
- @file:iti/applications/common/exceptions/biz_exp.py
- @file:iti/applications/extensions/error_handler.py
### 9. 数据库操作规范
#### 查询操作
使用 SQLAlchemy 2.0 风格:
```python
from sqlalchemy import select
# 单条查询
user = db.session.scalar(select(User).filter_by(id=user_id))
# 多条查询
users = db.session.scalars(select(User).filter_by(status="enabled")).all()
# 关联查询
user = db.session.scalar(
select(User)
.filter_by(id=user_id)
.options(joinedload(User.roles))
)
```
#### 事务处理
```python
try:
db.session.add(user)
db.session.commit()
except Exception as e:
db.session.rollback()
raise BizException("创建失败")
```
### 10. 认证和授权规范
#### JWT 认证
使用 `@jwt_required()` 装饰器:
```python
from flask_jwt_extended import jwt_required, current_user
@bp.get("/profile")
@jwt_required()
def get_profile():
"""获取当前用户信息"""
return success(current_user)
```
#### 权限检查
使用 `@permission_required()` 装饰器:
```python
from iti.applications.common.permission import permission_required
@bp.delete("/delete")
@jwt_required()
@permission_required("sys:user:delete")
def delete_user(user_id: str):
"""删除用户"""
# 业务逻辑
```
参考:
- @file:iti/applications/common/permission.py
### 11. 日志记录规范
#### 系统日志装饰器
使用 `@sys_log()` 装饰器记录操作日志:
```python
from iti.applications.extensions import sys_log
from iti.applications.common.enums import LogType
@sys_log(
name="创建用户",
desc="创建新用户",
type=LogType.OPERATION,
save_db=True,
execute_time=True,
)
def create_user():
# 业务逻辑
```
参考:
- @file:iti/applications/extensions/sys_log.py
### 12. 限流规范
#### 限流装饰器
使用 `@limiter.limit()` 装饰器:
```python
from iti.applications.extensions.limit import limiter
@bp.post("/sendCode")
@limiter.limit(limit_value="2 per minute")
def send_code():
"""发送验证码"""
# 业务逻辑
```
参考:
- @file:iti/applications/extensions/limit.py
### 13. 缓存使用规范
#### 缓存装饰器
```python
from iti.applications.extensions import cache_simple
@cache_simple.cached(timeout=300, key_prefix="user_")
def get_user_info(user_id: str):
"""获取用户信息(带缓存)"""
return db.session.scalar(select(User).filter_by(id=user_id))
```
#### 手动缓存操作
```python
cache_simple.set(key="cache_key", value=data, timeout=300)
cached_data = cache_simple.get(key="cache_key")
cache_simple.delete(key="cache_key")
```
参考:
- @file:iti/applications/extensions/cache.py
### 14. 文件存储规范
#### 文件上传
使用统一的文件存储接口:
```python
from iti.applications.common.storage.manager import storage_manager
file_url = storage_manager.save(
file=request.files['file'],
folder="uploads",
filename="custom_name.jpg"
)
```
参考:
- @file:iti/applications/common/storage/manager.py
### 15. 事件系统规范
#### 事件定义
在 `common/events.py` 中定义事件:
```python
class UserEvents(Enum):
USER_REGISTERED = "user.registered"
USER_LOGGED_IN = "user.logged_in"
```
#### 事件触发
```python
from iti.applications.extensions import eventbus
from iti.applications.common.events import UserEvents
eventbus.emit(UserEvents.USER_REGISTERED.value, user)
```
#### 事件处理
在 `events/` 目录创建事件处理器:
```python
from iti.applications.extensions.eventbus import event_handler
@event_handler("user.registered")
def on_user_registered(user, **kwargs):
"""用户注册事件处理"""
# 处理逻辑
```
参考:
- @file:iti/applications/common/events.py
- @file:iti/applications/events/user_cache_event_handler.py
### 16. 数据库迁移规范
#### 创建迁移
```bash
flask db migrate -m "描述信息"
```
#### 执行迁移
```bash
flask db upgrade
```
#### 回滚迁移
```bash
flask db downgrade
```
参考:
- @file:migrations/README
### 17. 响应格式规范
#### 成功响应
使用 `success()` 函数:
```python
from iti.applications.common.utils import success
return success(data, message="操作成功")
```
响应格式:
```json
{
"code": 200,
"data": {...},
"message": "操作成功"
}
```
#### 错误响应
通过异常自动处理,或手动返回:
```python
from iti.applications.common.utils import error
return error(message="错误信息", code=400)
```
### 18. 枚举定义规范
在 `common/enums.py` 中定义枚举:
```python
from enum import Enum
class StatusEnum(str, Enum):
ENABLED = "enabled"
DISABLED = "disabled"
```
在模型中使用:
```python
status = db.Column(
db.Enum(StatusEnum, values_callable=lambda x: [e.value for e in x]),
nullable=False,
default=StatusEnum.ENABLED.value,
)
```
参考:
- @file:iti/applications/common/enums.py
### 19. 工具函数规范
#### 通用工具
放在 `common/utils/` 目录:
- `http.py`: HTTP 响应工具
- `validate.py`: 验证工具
- `cache.py`: 缓存工具
- `tree.py`: 树形结构工具
参考:
- @file:iti/applications/common/utils/http.py
### 20. API 文档规范
#### 自动生成文档
APIFlask 自动生成 API 文档,访问:
- Swagger UI: `/docs`
- ReDoc: `/docs`
- Elements: `/docs` (默认)
#### 文档注解
使用 docstring 和 metadata
```python
@bp.post("/create")
@bp.input(CreateRequest.Schema, location="json")
def create(json_data: CreateRequest):
"""
创建资源
这是创建资源的接口,用于...
"""
# 业务逻辑
```
## 开发注意事项
1. **事务管理**: 确保数据库操作在事务中,异常时回滚
2. **N+1 查询**: 使用 `joinedload` 或 `selectinload` 避免 N+1 问题
3. **SQL 注入**: 使用参数化查询,不要拼接 SQL
4. **性能优化**: 合理使用缓存,避免重复查询
5. **错误处理**: 所有异常都要有适当的处理,不要暴露敏感信息
6. **日志记录**: 重要操作都要记录日志,便于排查问题
7. **类型提示**: 使用 Type Hints 提高代码可读性
8. **代码复用**: 公共逻辑提取到 service 或 utils
9. **AI规则**: AI编写代码时不要生成任何文档也不要写繁琐的注释除非特别需要
## 测试规范
### 单元测试
- 测试文件放在 `tests/` 目录
- 测试文件命名:`test_*.py`
- 使用 pytest 框架
### 测试示例
```python
def test_create_user(client):
response = client.post('/api/user', json={
'username': 'test',
'email': 'test@example.com'
})
assert response.status_code == 200
```
参考:
- @file:tests/test_http_utils.py