jalontsui-fastapi-kit 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- jalontsui_fastapi_kit/__init__.py +152 -0
- jalontsui_fastapi_kit/cache/README.md +195 -0
- jalontsui_fastapi_kit/cache/__init__.py +14 -0
- jalontsui_fastapi_kit/cache/redis.py +40 -0
- jalontsui_fastapi_kit/config/README.md +176 -0
- jalontsui_fastapi_kit/config/__init__.py +50 -0
- jalontsui_fastapi_kit/config/app.py +46 -0
- jalontsui_fastapi_kit/config/base.py +41 -0
- jalontsui_fastapi_kit/config/common.py +32 -0
- jalontsui_fastapi_kit/config/db.py +92 -0
- jalontsui_fastapi_kit/config/log.py +70 -0
- jalontsui_fastapi_kit/config/redis.py +114 -0
- jalontsui_fastapi_kit/config/security.py +30 -0
- jalontsui_fastapi_kit/config/storage.py +71 -0
- jalontsui_fastapi_kit/db/README.md +313 -0
- jalontsui_fastapi_kit/db/__init__.py +41 -0
- jalontsui_fastapi_kit/db/base.py +166 -0
- jalontsui_fastapi_kit/db/handlers.py +46 -0
- jalontsui_fastapi_kit/db/session.py +99 -0
- jalontsui_fastapi_kit/db/transaction.py +38 -0
- jalontsui_fastapi_kit/dependencies/__init__.py +32 -0
- jalontsui_fastapi_kit/dependencies/rate_limit.py +201 -0
- jalontsui_fastapi_kit/errors/README.md +334 -0
- jalontsui_fastapi_kit/errors/__init__.py +61 -0
- jalontsui_fastapi_kit/errors/codes.py +93 -0
- jalontsui_fastapi_kit/errors/exceptions.py +102 -0
- jalontsui_fastapi_kit/errors/handlers/__init__.py +28 -0
- jalontsui_fastapi_kit/errors/handlers/base.py +47 -0
- jalontsui_fastapi_kit/errors/handlers/builtin.py +126 -0
- jalontsui_fastapi_kit/errors/handlers/registry.py +105 -0
- jalontsui_fastapi_kit/errors/handlers/utils.py +30 -0
- jalontsui_fastapi_kit/errors/messages.py +172 -0
- jalontsui_fastapi_kit/health/README.md +178 -0
- jalontsui_fastapi_kit/health/__init__.py +97 -0
- jalontsui_fastapi_kit/logging/README.md +220 -0
- jalontsui_fastapi_kit/logging/__init__.py +61 -0
- jalontsui_fastapi_kit/logging/config.py +341 -0
- jalontsui_fastapi_kit/logging/context.py +44 -0
- jalontsui_fastapi_kit/logging/filters.py +40 -0
- jalontsui_fastapi_kit/logging/formatters.py +119 -0
- jalontsui_fastapi_kit/logging/handlers.py +170 -0
- jalontsui_fastapi_kit/logging/settings.py +44 -0
- jalontsui_fastapi_kit/logging/utils.py +212 -0
- jalontsui_fastapi_kit/middleware/README.md +191 -0
- jalontsui_fastapi_kit/middleware/__init__.py +25 -0
- jalontsui_fastapi_kit/middleware/cors.py +45 -0
- jalontsui_fastapi_kit/middleware/locale.py +122 -0
- jalontsui_fastapi_kit/middleware/request_id.py +116 -0
- jalontsui_fastapi_kit/py.typed +0 -0
- jalontsui_fastapi_kit/repositories/README.md +170 -0
- jalontsui_fastapi_kit/repositories/__init__.py +11 -0
- jalontsui_fastapi_kit/repositories/base.py +162 -0
- jalontsui_fastapi_kit/repositories/utils.py +80 -0
- jalontsui_fastapi_kit/response.py +47 -0
- jalontsui_fastapi_kit/schemas/README.md +166 -0
- jalontsui_fastapi_kit/schemas/common.py +64 -0
- jalontsui_fastapi_kit/search/README.md +176 -0
- jalontsui_fastapi_kit/search/__init__.py +15 -0
- jalontsui_fastapi_kit/search/elasticsearch.py +50 -0
- jalontsui_fastapi_kit/security/README.md +244 -0
- jalontsui_fastapi_kit/security/__init__.py +33 -0
- jalontsui_fastapi_kit/security/captcha.py +113 -0
- jalontsui_fastapi_kit/security/jwt.py +92 -0
- jalontsui_fastapi_kit/security/password.py +94 -0
- jalontsui_fastapi_kit/services/README.md +113 -0
- jalontsui_fastapi_kit/services/__init__.py +5 -0
- jalontsui_fastapi_kit/services/base.py +68 -0
- jalontsui_fastapi_kit/storage/__init__.py +49 -0
- jalontsui_fastapi_kit/storage/base.py +75 -0
- jalontsui_fastapi_kit/storage/factory.py +96 -0
- jalontsui_fastapi_kit/storage/local.py +88 -0
- jalontsui_fastapi_kit/storage/s3.py +184 -0
- jalontsui_fastapi_kit/utils/__init__.py +6 -0
- jalontsui_fastapi_kit/utils/time.py +66 -0
- jalontsui_fastapi_kit/validation/README.md +164 -0
- jalontsui_fastapi_kit/validation/__init__.py +15 -0
- jalontsui_fastapi_kit/validation/errors.py +207 -0
- jalontsui_fastapi_kit-0.1.0.dist-info/METADATA +136 -0
- jalontsui_fastapi_kit-0.1.0.dist-info/RECORD +81 -0
- jalontsui_fastapi_kit-0.1.0.dist-info/WHEEL +4 -0
- jalontsui_fastapi_kit-0.1.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"""jalontsui-common —— 项目公共基础设施包."""
|
|
2
|
+
|
|
3
|
+
from jalontsui_fastapi_kit.cache import RedisClient, create_redis_client
|
|
4
|
+
from jalontsui_fastapi_kit.config import BaseAppSettings
|
|
5
|
+
from jalontsui_fastapi_kit.db import (
|
|
6
|
+
Base,
|
|
7
|
+
close_async_engine,
|
|
8
|
+
create_async_engine_from_url,
|
|
9
|
+
create_async_session_factory,
|
|
10
|
+
transaction,
|
|
11
|
+
)
|
|
12
|
+
from jalontsui_fastapi_kit.errors import (
|
|
13
|
+
BadRequestException,
|
|
14
|
+
BusinessException,
|
|
15
|
+
DatabaseConflictException,
|
|
16
|
+
DatabaseIntegrityException,
|
|
17
|
+
ErrorMessageRegistry,
|
|
18
|
+
ExceptionHandler,
|
|
19
|
+
ExceptionHandlerRegistry,
|
|
20
|
+
ExternalServiceException,
|
|
21
|
+
ForbiddenException,
|
|
22
|
+
NotFoundException,
|
|
23
|
+
UnauthorizedException,
|
|
24
|
+
ValidationException,
|
|
25
|
+
get_message,
|
|
26
|
+
set_default_locale,
|
|
27
|
+
set_request_locale,
|
|
28
|
+
)
|
|
29
|
+
from jalontsui_fastapi_kit.health import (
|
|
30
|
+
HealthChecker,
|
|
31
|
+
HealthCheckResponse,
|
|
32
|
+
HealthResult,
|
|
33
|
+
check_database,
|
|
34
|
+
check_redis,
|
|
35
|
+
)
|
|
36
|
+
from jalontsui_fastapi_kit.logging import (
|
|
37
|
+
DEFAULT_LOG_FORMAT,
|
|
38
|
+
RequestIdFilter,
|
|
39
|
+
get_request_id,
|
|
40
|
+
parse_level,
|
|
41
|
+
request_id_ctx,
|
|
42
|
+
setup_logging,
|
|
43
|
+
)
|
|
44
|
+
from jalontsui_fastapi_kit.middleware import (
|
|
45
|
+
REQUEST_ID_HEADER,
|
|
46
|
+
LocaleMiddleware,
|
|
47
|
+
RequestIdMiddleware,
|
|
48
|
+
setup_cors,
|
|
49
|
+
)
|
|
50
|
+
from jalontsui_fastapi_kit.repositories.base import BaseRepository
|
|
51
|
+
from jalontsui_fastapi_kit.response import ApiResponse
|
|
52
|
+
from jalontsui_fastapi_kit.schemas.common import (
|
|
53
|
+
ListResponse,
|
|
54
|
+
PageResponse,
|
|
55
|
+
ScrollPageResponse,
|
|
56
|
+
)
|
|
57
|
+
from jalontsui_fastapi_kit.search import (
|
|
58
|
+
ElasticsearchClient,
|
|
59
|
+
create_elasticsearch_client,
|
|
60
|
+
)
|
|
61
|
+
from jalontsui_fastapi_kit.services import BaseService
|
|
62
|
+
from jalontsui_fastapi_kit.utils.time import utc_naive_to_local, utc_naive_to_local_str
|
|
63
|
+
from jalontsui_fastapi_kit.security import (
|
|
64
|
+
captcha_image_to_base64,
|
|
65
|
+
generate_captcha_code,
|
|
66
|
+
generate_captcha_image,
|
|
67
|
+
hash_password,
|
|
68
|
+
password_needs_rehash,
|
|
69
|
+
verify_password,
|
|
70
|
+
)
|
|
71
|
+
from jalontsui_fastapi_kit.validation import (
|
|
72
|
+
ValidationErrorItem,
|
|
73
|
+
format_validation_errors,
|
|
74
|
+
validation_errors_to_dict,
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
__all__ = [
|
|
78
|
+
# cache
|
|
79
|
+
"RedisClient",
|
|
80
|
+
"create_redis_client",
|
|
81
|
+
# config
|
|
82
|
+
"BaseAppSettings",
|
|
83
|
+
# db
|
|
84
|
+
"Base",
|
|
85
|
+
"create_async_engine_from_url",
|
|
86
|
+
"create_async_session_factory",
|
|
87
|
+
"close_async_engine",
|
|
88
|
+
# errors
|
|
89
|
+
"ErrorMessageRegistry",
|
|
90
|
+
"get_message",
|
|
91
|
+
"set_default_locale",
|
|
92
|
+
"set_request_locale",
|
|
93
|
+
"BusinessException",
|
|
94
|
+
"NotFoundException",
|
|
95
|
+
"ValidationException",
|
|
96
|
+
"BadRequestException",
|
|
97
|
+
"UnauthorizedException",
|
|
98
|
+
"ForbiddenException",
|
|
99
|
+
"DatabaseConflictException",
|
|
100
|
+
"DatabaseIntegrityException",
|
|
101
|
+
"ExternalServiceException",
|
|
102
|
+
# handlers
|
|
103
|
+
"ExceptionHandler",
|
|
104
|
+
"ExceptionHandlerRegistry",
|
|
105
|
+
# health
|
|
106
|
+
"HealthChecker",
|
|
107
|
+
"HealthCheckResponse",
|
|
108
|
+
"HealthResult",
|
|
109
|
+
"check_database",
|
|
110
|
+
"check_redis",
|
|
111
|
+
# logging
|
|
112
|
+
"DEFAULT_LOG_FORMAT",
|
|
113
|
+
"RequestIdFilter",
|
|
114
|
+
"get_request_id",
|
|
115
|
+
"parse_level",
|
|
116
|
+
"request_id_ctx",
|
|
117
|
+
"setup_logging",
|
|
118
|
+
# middleware
|
|
119
|
+
"REQUEST_ID_HEADER",
|
|
120
|
+
"RequestIdMiddleware",
|
|
121
|
+
"LocaleMiddleware",
|
|
122
|
+
"setup_cors",
|
|
123
|
+
# repositories
|
|
124
|
+
"BaseRepository",
|
|
125
|
+
# response
|
|
126
|
+
"ApiResponse",
|
|
127
|
+
# services
|
|
128
|
+
"BaseService",
|
|
129
|
+
# transaction
|
|
130
|
+
"transaction",
|
|
131
|
+
# schemas
|
|
132
|
+
"ListResponse",
|
|
133
|
+
"PageResponse",
|
|
134
|
+
"ScrollPageResponse",
|
|
135
|
+
# search
|
|
136
|
+
"ElasticsearchClient",
|
|
137
|
+
"create_elasticsearch_client",
|
|
138
|
+
# security
|
|
139
|
+
"hash_password",
|
|
140
|
+
"verify_password",
|
|
141
|
+
"password_needs_rehash",
|
|
142
|
+
"generate_captcha_code",
|
|
143
|
+
"generate_captcha_image",
|
|
144
|
+
"captcha_image_to_base64",
|
|
145
|
+
# utils
|
|
146
|
+
"utc_naive_to_local",
|
|
147
|
+
"utc_naive_to_local_str",
|
|
148
|
+
# validation
|
|
149
|
+
"ValidationErrorItem",
|
|
150
|
+
"format_validation_errors",
|
|
151
|
+
"validation_errors_to_dict",
|
|
152
|
+
]
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# jalontsui_fastapi_kit.cache 使用指南
|
|
2
|
+
|
|
3
|
+
> **适用包**:`packages/jalontsui-fastapi-kit`
|
|
4
|
+
> **作用域**:所有需要缓存/消息队列连接的 Python 服务
|
|
5
|
+
> **最后更新**:2026-07-14
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 目录
|
|
10
|
+
|
|
11
|
+
1. [设计定位](#1-设计定位)
|
|
12
|
+
2. [目录结构](#2-目录结构)
|
|
13
|
+
3. [快速开始](#3-快速开始)
|
|
14
|
+
4. [创建 Redis 客户端](#4-创建-redis-客户端)
|
|
15
|
+
5. [URL 格式](#5-url-格式)
|
|
16
|
+
6. [健康检查](#6-健康检查)
|
|
17
|
+
7. [关闭客户端](#7-关闭客户端)
|
|
18
|
+
8. [扩展其他缓存后端](#8-扩展其他缓存后端)
|
|
19
|
+
9. [最佳实践](#9-最佳实践)
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## 1. 设计定位
|
|
24
|
+
|
|
25
|
+
`jalontsui_fastapi_kit.cache` 是项目统一的缓存/消息队列连接基础设施:
|
|
26
|
+
|
|
27
|
+
- 目前提供 **Redis 异步客户端工厂**。
|
|
28
|
+
- 未来可按同样模式新增 **Kafka、RabbitMQ、NATS** 等后端模块。
|
|
29
|
+
- 对业务代码屏蔽连接细节,统一通过 URL 创建客户端。
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## 2. 目录结构
|
|
34
|
+
|
|
35
|
+
```text
|
|
36
|
+
packages/jalontsui-fastapi-kit/src/jalontsui_fastapi_kit/cache/
|
|
37
|
+
├── __init__.py # 公共 API 导出
|
|
38
|
+
└── redis.py # Redis 异步客户端工厂
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## 3. 快速开始
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
from jalontsui_fastapi_kit.cache import create_redis_client
|
|
47
|
+
|
|
48
|
+
client = create_redis_client("redis://localhost:6379/0")
|
|
49
|
+
|
|
50
|
+
await client.ping()
|
|
51
|
+
await client.set("key", "value", ex=60)
|
|
52
|
+
value = await client.get("key")
|
|
53
|
+
|
|
54
|
+
await client.close()
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## 4. 创建 Redis 客户端
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
from jalontsui_fastapi_kit.cache import create_redis_client, RedisClient
|
|
63
|
+
|
|
64
|
+
client: RedisClient = create_redis_client(
|
|
65
|
+
"redis://:mypassword@localhost:6379/0",
|
|
66
|
+
decode_responses=True, # 默认开启,自动解码为字符串
|
|
67
|
+
socket_connect_timeout=5,
|
|
68
|
+
socket_keepalive=True,
|
|
69
|
+
health_check_interval=30,
|
|
70
|
+
)
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### 常用参数
|
|
74
|
+
|
|
75
|
+
| 参数 | 说明 | 默认值 |
|
|
76
|
+
|------|------|--------|
|
|
77
|
+
| `url` | Redis 连接串 | 必填 |
|
|
78
|
+
| `decode_responses` | 是否自动解码响应 | `True` |
|
|
79
|
+
| `socket_connect_timeout` | 连接超时(秒) | 依赖 redis-py 默认 |
|
|
80
|
+
| `socket_keepalive` | 是否保持长连接 | `False` |
|
|
81
|
+
| `health_check_interval` | 健康检查间隔(秒) | `0` |
|
|
82
|
+
|
|
83
|
+
更多参数见 [redis-py 文档](https://redis-py.readthedocs.io/en/stable/connections.html)。
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## 5. URL 格式
|
|
88
|
+
|
|
89
|
+
```text
|
|
90
|
+
redis://[:password@]host:port/db
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
示例:
|
|
94
|
+
|
|
95
|
+
```text
|
|
96
|
+
redis://localhost:6379/0
|
|
97
|
+
redis://:mypassword@redis.example.com:6379/0
|
|
98
|
+
rediss://:mypassword@redis.example.com:6380/0 # SSL
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
在 `packages/web` 中,可通过 `settings.redis_url` 获取统一构建的连接串:
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
from web.config import settings
|
|
105
|
+
from jalontsui_fastapi_kit.cache import create_redis_client
|
|
106
|
+
|
|
107
|
+
client = create_redis_client(settings.redis_url)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## 6. 健康检查
|
|
113
|
+
|
|
114
|
+
`jalontsui_fastapi_kit.health.check_redis` 可探测 Redis 是否可达:
|
|
115
|
+
|
|
116
|
+
```python
|
|
117
|
+
from jalontsui_fastapi_kit.cache import create_redis_client
|
|
118
|
+
from jalontsui_fastapi_kit.health import check_redis
|
|
119
|
+
|
|
120
|
+
client = create_redis_client("redis://localhost:6379/0")
|
|
121
|
+
result = await check_redis(client)
|
|
122
|
+
|
|
123
|
+
print(result.status) # "ok" or "error"
|
|
124
|
+
print(result.latency_ms) # 延迟毫秒
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
在 FastAPI `/health` 端点中的典型用法:
|
|
128
|
+
|
|
129
|
+
```python
|
|
130
|
+
from jalontsui_fastapi_kit.cache import create_redis_client
|
|
131
|
+
from jalontsui_fastapi_kit.health import HealthChecker, check_database, check_redis
|
|
132
|
+
from web.config import settings
|
|
133
|
+
from web.database import AsyncSessionLocal
|
|
134
|
+
|
|
135
|
+
redis_client = create_redis_client(settings.redis_url)
|
|
136
|
+
|
|
137
|
+
checker = HealthChecker()
|
|
138
|
+
checker.register("database", lambda: check_database(async_session))
|
|
139
|
+
checker.register("redis", lambda: check_redis(redis_client))
|
|
140
|
+
|
|
141
|
+
response = await checker.run()
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## 7. 关闭客户端
|
|
147
|
+
|
|
148
|
+
```python
|
|
149
|
+
await client.close()
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
在 FastAPI `lifespan` 中集中管理:
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
from contextlib import asynccontextmanager
|
|
156
|
+
from fastapi import FastAPI
|
|
157
|
+
from jalontsui_fastapi_kit.cache import create_redis_client
|
|
158
|
+
from web.config import settings
|
|
159
|
+
|
|
160
|
+
redis_client = create_redis_client(settings.redis_url)
|
|
161
|
+
|
|
162
|
+
@asynccontextmanager
|
|
163
|
+
async def lifespan(app: FastAPI):
|
|
164
|
+
yield
|
|
165
|
+
await redis_client.close()
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## 8. 扩展其他缓存后端
|
|
171
|
+
|
|
172
|
+
未来新增缓存/消息队列后端的步骤:
|
|
173
|
+
|
|
174
|
+
1. 在 `packages/jalontsui-fastapi-kit/pyproject.toml` 安装对应依赖。
|
|
175
|
+
2. 在 `common/cache/` 下新增模块,例如 `common/cache/kafka.py`。
|
|
176
|
+
3. 在 `common/cache/__init__.py` 中导出新的工厂函数。
|
|
177
|
+
|
|
178
|
+
示例结构:
|
|
179
|
+
|
|
180
|
+
```text
|
|
181
|
+
common/cache/
|
|
182
|
+
├── __init__.py
|
|
183
|
+
├── redis.py
|
|
184
|
+
└── kafka.py
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## 9. 最佳实践
|
|
190
|
+
|
|
191
|
+
- **统一使用 URL 创建客户端**:避免在业务代码中分散拼接 host/port/password。
|
|
192
|
+
- **配置集中管理**:推荐在 `Settings` 中提供 `redis_url` 属性。
|
|
193
|
+
- **生命周期统一管理**:应用启动时创建,关闭时 `close()` 释放。
|
|
194
|
+
- **生产环境启用 SSL**:使用 `rediss://` 协议。
|
|
195
|
+
- **合理设置超时**:避免网络抖动导致请求长时间挂起。
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""通用缓存/消息队列连接工具.
|
|
2
|
+
|
|
3
|
+
目前提供 Redis 异步客户端工厂,后续可按同样模式新增
|
|
4
|
+
Kafka、RabbitMQ、NATS 等后端模块.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from redis.asyncio import Redis as RedisClient
|
|
8
|
+
|
|
9
|
+
from jalontsui_fastapi_kit.cache.redis import create_redis_client
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"RedisClient",
|
|
13
|
+
"create_redis_client",
|
|
14
|
+
]
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"""Redis 异步客户端工厂."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any, cast
|
|
6
|
+
|
|
7
|
+
import redis.asyncio as aioredis
|
|
8
|
+
|
|
9
|
+
RedisClient = aioredis.Redis
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def create_redis_client(
|
|
13
|
+
url: str,
|
|
14
|
+
*,
|
|
15
|
+
decode_responses: bool = True,
|
|
16
|
+
**kwargs: Any,
|
|
17
|
+
) -> RedisClient:
|
|
18
|
+
"""根据 Redis URL 创建异步客户端.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
url: Redis 连接串,例如 redis://[:password@]host:port/db。
|
|
22
|
+
decode_responses: 是否自动将响应解码为字符串,默认开启。
|
|
23
|
+
**kwargs: 透传给 redis.asyncio.Redis.from_url 的其他参数,
|
|
24
|
+
常用于设置 socket_connect_timeout、socket_keepalive、health_check_interval 等。
|
|
25
|
+
|
|
26
|
+
Returns:
|
|
27
|
+
redis.asyncio.Redis 实例。
|
|
28
|
+
|
|
29
|
+
Example:
|
|
30
|
+
>>> client = create_redis_client("redis://localhost:6379/0")
|
|
31
|
+
>>> await client.ping()
|
|
32
|
+
"""
|
|
33
|
+
return cast(
|
|
34
|
+
RedisClient,
|
|
35
|
+
aioredis.Redis.from_url(
|
|
36
|
+
url,
|
|
37
|
+
decode_responses=decode_responses,
|
|
38
|
+
**kwargs,
|
|
39
|
+
),
|
|
40
|
+
)
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# jalontsui_fastapi_kit.config 使用指南
|
|
2
|
+
|
|
3
|
+
> **适用包**:`packages/jalontsui-fastapi-kit`
|
|
4
|
+
> **作用域**:所有需要基于环境变量 / `.env` 管理配置的 Python 服务
|
|
5
|
+
> **最后更新**:2026-07-16
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 目录
|
|
10
|
+
|
|
11
|
+
1. [设计定位](#1-设计定位)
|
|
12
|
+
2. [目录结构](#2-目录结构)
|
|
13
|
+
3. [快速开始](#3-快速开始)
|
|
14
|
+
4. [配置读取优先级](#4-配置读取优先级)
|
|
15
|
+
5. [继承扩展](#5-继承扩展)
|
|
16
|
+
6. [环境判断属性](#6-环境判断属性)
|
|
17
|
+
7. [最佳实践](#7-最佳实践)
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## 1. 设计定位
|
|
22
|
+
|
|
23
|
+
`jalontsui_fastapi_kit.config` 提供基于 [pydantic-settings](https://docs.pydantic.dev/latest/concepts/pydantic_settings/) 的通用配置基类 `BaseAppSettings`:
|
|
24
|
+
|
|
25
|
+
- 统一配置读取入口(环境变量 + `.env` 文件)。
|
|
26
|
+
- 内置应用名称、调试开关、运行环境、数据库、Redis、日志、JWT 等通用字段。
|
|
27
|
+
- 各配置分块通过**多继承**扁平组合,字段统一携带分块前缀,子类继承后可直接访问。
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## 2. 目录结构
|
|
32
|
+
|
|
33
|
+
```text
|
|
34
|
+
packages/jalontsui-fastapi-kit/src/jalontsui_fastapi_kit/config/
|
|
35
|
+
├── __init__.py # 统一组合入口 BaseAppSettings(多继承各配置分块)
|
|
36
|
+
├── base.py # 通用配置骨架 BaseAppConfig
|
|
37
|
+
├── app.py # 应用基础配置 AppConfig(app_* 字段)
|
|
38
|
+
├── common.py # 公共配置 CommonConfig(common_* 字段)
|
|
39
|
+
├── db.py # 数据库配置 DatabaseConfig(db_* 字段)
|
|
40
|
+
├── redis.py # Redis 配置 RedisConfig(redis_* 字段)
|
|
41
|
+
├── log.py # 日志配置 LogConfig(log_* 字段)
|
|
42
|
+
├── security.py # 安全配置 SecurityConfig(jwt_* 等字段)
|
|
43
|
+
└── README.md # 本文档
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## 3. 快速开始
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
from jalontsui_fastapi_kit.config import BaseAppSettings
|
|
52
|
+
|
|
53
|
+
settings = BaseAppSettings()
|
|
54
|
+
|
|
55
|
+
print(settings.app_name) # "app"(默认值)
|
|
56
|
+
print(settings.app_env) # "development"(默认值)
|
|
57
|
+
print(settings.app_debug) # False(默认值)
|
|
58
|
+
print(settings.app_env == "development") # True,也可用 is_development 属性
|
|
59
|
+
print(settings.log_level) # None(默认值)
|
|
60
|
+
print(settings.log_path) # "logs"(默认值)
|
|
61
|
+
print(settings.log_filename) # "app.log"(默认值)
|
|
62
|
+
print(settings.db_host) # "localhost"(默认值)
|
|
63
|
+
print(settings.redis_port) # 6379(默认值)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## 4. 配置读取优先级
|
|
69
|
+
|
|
70
|
+
pydantic-settings 读取优先级(高 → 低):
|
|
71
|
+
|
|
72
|
+
1. 环境变量
|
|
73
|
+
2. 当前工作目录下的 `.env` 文件(或 `ENV_FILE` 指定的配置文件)
|
|
74
|
+
3. 类中定义的默认值
|
|
75
|
+
|
|
76
|
+
字段统一携带分块前缀,**环境变量名即字段名的大写形式**(大小写不敏感),无需嵌套分隔符。示例 `.env`:
|
|
77
|
+
|
|
78
|
+
```env
|
|
79
|
+
APP_NAME=jalontsui-web
|
|
80
|
+
APP_ENV=production
|
|
81
|
+
APP_DEBUG=true
|
|
82
|
+
LOG_LEVEL=INFO
|
|
83
|
+
LOG_PATH=logs
|
|
84
|
+
DB_HOST=localhost
|
|
85
|
+
DB_PORT=3306
|
|
86
|
+
REDIS_HOST=localhost
|
|
87
|
+
REDIS_PORT=6379
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
from jalontsui_fastapi_kit.config import BaseAppSettings
|
|
92
|
+
|
|
93
|
+
settings = BaseAppSettings()
|
|
94
|
+
print(settings.app_name) # "jalontsui-web"
|
|
95
|
+
print(settings.app_env) # "production"
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## 5. 继承扩展
|
|
101
|
+
|
|
102
|
+
业务项目应继承 `BaseAppSettings`,直接重定义字段即可覆盖默认值,并添加业务专属字段:
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
from pydantic import Field
|
|
106
|
+
from jalontsui_fastapi_kit.config import BaseAppSettings
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
class AppSettings(BaseAppSettings):
|
|
110
|
+
"""业务应用配置."""
|
|
111
|
+
|
|
112
|
+
# 覆盖通用配置默认值
|
|
113
|
+
app_name: str = Field(default="my-service")
|
|
114
|
+
db_name: str = Field(default="my_db")
|
|
115
|
+
|
|
116
|
+
# 业务专属字段
|
|
117
|
+
database_url: str = Field(
|
|
118
|
+
default="mysql+asyncmy://root@localhost:3306/mydb",
|
|
119
|
+
description="异步数据库连接串",
|
|
120
|
+
)
|
|
121
|
+
secret_key: str = Field(
|
|
122
|
+
default="change-me",
|
|
123
|
+
description="JWT / 加密密钥",
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
settings = AppSettings()
|
|
128
|
+
print(settings.app_name) # "my-service"(覆盖后的默认值)
|
|
129
|
+
print(settings.log_path) # "logs"(继承自通用配置)
|
|
130
|
+
print(settings.database_url) # 业务自定义字段
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
> 字段名大小写不敏感(`case_sensitive=False`),`database_url` 与 `DATABASE_URL` 等价。
|
|
134
|
+
|
|
135
|
+
若业务方不需要全部配置分块,也可自行组合,例如网关不需要数据库配置:
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
from jalontsui_fastapi_kit.config import BaseAppConfig, AppConfig, LogConfig, RedisConfig
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
class GatewaySettings(BaseAppConfig, AppConfig, LogConfig, RedisConfig):
|
|
142
|
+
"""网关配置,仅组合所需分块."""
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## 6. 环境判断属性
|
|
148
|
+
|
|
149
|
+
`AppConfig` 提供三个便捷属性:
|
|
150
|
+
|
|
151
|
+
```python
|
|
152
|
+
from jalontsui_fastapi_kit.config import BaseAppSettings
|
|
153
|
+
|
|
154
|
+
settings = BaseAppSettings(app_env="production")
|
|
155
|
+
|
|
156
|
+
assert settings.is_production is True
|
|
157
|
+
assert settings.is_development is False
|
|
158
|
+
assert settings.is_testing is False
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
常用于根据环境调整行为:
|
|
162
|
+
|
|
163
|
+
```python
|
|
164
|
+
if settings.is_development:
|
|
165
|
+
enable_auto_reload()
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## 7. 最佳实践
|
|
171
|
+
|
|
172
|
+
- **业务项目必须继承扩展**:不要在业务代码中直接使用裸 `BaseAppSettings`。
|
|
173
|
+
- **敏感字段走环境变量**:`jwt_secret_key`、数据库密码等不要写进代码或提交默认值。
|
|
174
|
+
- **集中单例管理**:通常在业务包的 `config.py` 中实例化一次全局 `settings`,供全应用引用。
|
|
175
|
+
- **字段描述要完整**:使用 `Field(description=...)` 说明用途,便于生成文档和 `.env.example`。
|
|
176
|
+
- **新增配置分块**:参考 `packages/jalontsui-fastapi-kit/AGENTS.md` 第 2 节的标准流程,字段统一携带分块前缀。
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"""通用应用配置.
|
|
2
|
+
|
|
3
|
+
本包按功能域拆分到多个模块,每个配置分块都是 BaseAppConfig 的子类,
|
|
4
|
+
字段统一携带分块前缀(如 ``app_name`` / ``db_host`` / ``redis_host``)。
|
|
5
|
+
BaseAppSettings 通过多继承直接组合各配置分块,使用方实例化一次即可扁平地
|
|
6
|
+
读取全部配置(如 ``settings.app_name`` / ``settings.db_host``)。
|
|
7
|
+
环境变量名与字段名一一对应(大小写不敏感),例如 ``APP_NAME``、``DB_HOST``。
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from jalontsui_fastapi_kit.config.app import AppConfig
|
|
13
|
+
from jalontsui_fastapi_kit.config.base import BaseAppConfig
|
|
14
|
+
from jalontsui_fastapi_kit.config.common import CommonConfig
|
|
15
|
+
from jalontsui_fastapi_kit.config.db import DatabaseConfig
|
|
16
|
+
from jalontsui_fastapi_kit.config.log import LogConfig
|
|
17
|
+
from jalontsui_fastapi_kit.config.redis import RedisConfig
|
|
18
|
+
from jalontsui_fastapi_kit.config.security import SecurityConfig
|
|
19
|
+
from jalontsui_fastapi_kit.config.storage import StorageConfig
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class BaseAppSettings(
|
|
23
|
+
AppConfig,
|
|
24
|
+
CommonConfig,
|
|
25
|
+
DatabaseConfig,
|
|
26
|
+
RedisConfig,
|
|
27
|
+
LogConfig,
|
|
28
|
+
SecurityConfig,
|
|
29
|
+
StorageConfig,
|
|
30
|
+
):
|
|
31
|
+
"""默认装配的通用应用配置.
|
|
32
|
+
|
|
33
|
+
通过多继承直接组合 app、common、db、redis、log、security 与 storage 七个通用配置域
|
|
34
|
+
(各分块本身已继承 BaseAppConfig,此处无需重复列出,否则会产生 MRO 冲突),
|
|
35
|
+
所有字段以 ``<分块>_`` 前缀扁平展开,可直接通过 ``settings.app_name`` 等方式访问。
|
|
36
|
+
如果业务方需要自定义装配其他配置域,可自行继承 BaseAppConfig 与所需配置分块组合。
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
__all__ = [
|
|
41
|
+
"AppConfig",
|
|
42
|
+
"BaseAppConfig",
|
|
43
|
+
"BaseAppSettings",
|
|
44
|
+
"CommonConfig",
|
|
45
|
+
"DatabaseConfig",
|
|
46
|
+
"LogConfig",
|
|
47
|
+
"RedisConfig",
|
|
48
|
+
"SecurityConfig",
|
|
49
|
+
"StorageConfig",
|
|
50
|
+
]
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""应用基础配置."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Literal
|
|
6
|
+
|
|
7
|
+
from pydantic import Field
|
|
8
|
+
|
|
9
|
+
from jalontsui_fastapi_kit.config.base import BaseAppConfig
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class AppConfig(BaseAppConfig):
|
|
13
|
+
"""应用基础配置.
|
|
14
|
+
|
|
15
|
+
主要包含应用名称、运行环境、调试开关等通用元信息。
|
|
16
|
+
字段统一携带 ``app_`` 前缀,环境变量名即字段名的大写形式
|
|
17
|
+
(如 ``APP_NAME`` / ``APP_ENV`` / ``APP_DEBUG``)。
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
app_name: str = Field(
|
|
21
|
+
default="app",
|
|
22
|
+
description="应用名称,主要用于日志与文档展示",
|
|
23
|
+
)
|
|
24
|
+
app_env: Literal["development", "testing", "production"] = Field(
|
|
25
|
+
default="development",
|
|
26
|
+
description="应用运行环境,影响日志级别等默认行为",
|
|
27
|
+
)
|
|
28
|
+
app_debug: bool = Field(
|
|
29
|
+
default=False,
|
|
30
|
+
description="调试模式,开启后会输出更详细的错误信息",
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
@property
|
|
34
|
+
def is_development(self) -> bool:
|
|
35
|
+
"""是否为开发环境."""
|
|
36
|
+
return self.app_env == "development"
|
|
37
|
+
|
|
38
|
+
@property
|
|
39
|
+
def is_testing(self) -> bool:
|
|
40
|
+
"""是否为测试环境."""
|
|
41
|
+
return self.app_env == "testing"
|
|
42
|
+
|
|
43
|
+
@property
|
|
44
|
+
def is_production(self) -> bool:
|
|
45
|
+
"""是否为生产环境."""
|
|
46
|
+
return self.app_env == "production"
|