feat: initialize Django DRF skeleton
This commit is contained in:
@@ -25,7 +25,7 @@ Python 3.12 / Django 5.2 LTS + DRF / django-admin / 用户端 Django 模板 SSR
|
|||||||
|
|
||||||
## 当前状态
|
## 当前状态
|
||||||
|
|
||||||
MVP 起步:目前仅有文档,尚无代码。下一步是 T-001 初始化 Django 骨架。详见 [`docs/current-state.md`](docs/current-state.md)。
|
MVP 起步:T-001 Django + DRF 最小骨架已完成,`manage.py` / `config/` 可运行。下一步是 T-002 建立 apps 目录、自定义 User 与配置。详见 [`docs/current-state.md`](docs/current-state.md)。
|
||||||
|
|
||||||
> ⚠️ 涉及资金/点数。改动充值、扣费、退款、对账相关代码前,先读 [`docs/05-coding-rules.md`](docs/05-coding-rules.md) 第 8 节与 [`docs/04-architecture.md`](docs/04-architecture.md) 第四节计费时序。
|
> ⚠️ 涉及资金/点数。改动充值、扣费、退款、对账相关代码前,先读 [`docs/05-coding-rules.md`](docs/05-coding-rules.md) 第 8 节与 [`docs/04-architecture.md`](docs/04-architecture.md) 第四节计费时序。
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
"""
|
||||||
|
ASGI config for config project.
|
||||||
|
|
||||||
|
It exposes the ASGI callable as a module-level variable named ``application``.
|
||||||
|
|
||||||
|
For more information on this file, see
|
||||||
|
https://docs.djangoproject.com/en/5.2/howto/deployment/asgi/
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from django.core.asgi import get_asgi_application
|
||||||
|
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')
|
||||||
|
|
||||||
|
application = get_asgi_application()
|
||||||
@@ -0,0 +1,136 @@
|
|||||||
|
"""
|
||||||
|
Django settings for config project.
|
||||||
|
|
||||||
|
Generated by 'django-admin startproject' using Django 5.2.15.
|
||||||
|
|
||||||
|
For more information on this file, see
|
||||||
|
https://docs.djangoproject.com/en/5.2/topics/settings/
|
||||||
|
|
||||||
|
For the full list of settings and their values, see
|
||||||
|
https://docs.djangoproject.com/en/5.2/ref/settings/
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||||
|
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||||
|
|
||||||
|
|
||||||
|
# Quick-start development settings - unsuitable for production
|
||||||
|
# See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/
|
||||||
|
|
||||||
|
def env_bool(name: str, default: bool = False) -> bool:
|
||||||
|
value = os.environ.get(name)
|
||||||
|
if value is None:
|
||||||
|
return default
|
||||||
|
return value.strip().lower() in {"1", "true", "yes", "on"}
|
||||||
|
|
||||||
|
|
||||||
|
def env_list(name: str, default: str = "") -> list[str]:
|
||||||
|
value = os.environ.get(name, default)
|
||||||
|
return [item.strip() for item in value.split(",") if item.strip()]
|
||||||
|
|
||||||
|
|
||||||
|
# SECURITY WARNING: keep the secret key used in production secret.
|
||||||
|
SECRET_KEY = os.environ.get("DJANGO_SECRET_KEY", "django-insecure-dev-only-change-me")
|
||||||
|
|
||||||
|
# SECURITY WARNING: don't run with debug turned on in production!
|
||||||
|
DEBUG = env_bool("DJANGO_DEBUG", True)
|
||||||
|
|
||||||
|
ALLOWED_HOSTS = env_list("DJANGO_ALLOWED_HOSTS", "127.0.0.1,localhost")
|
||||||
|
|
||||||
|
|
||||||
|
# Application definition
|
||||||
|
|
||||||
|
INSTALLED_APPS = [
|
||||||
|
'rest_framework',
|
||||||
|
'django.contrib.admin',
|
||||||
|
'django.contrib.auth',
|
||||||
|
'django.contrib.contenttypes',
|
||||||
|
'django.contrib.sessions',
|
||||||
|
'django.contrib.messages',
|
||||||
|
'django.contrib.staticfiles',
|
||||||
|
]
|
||||||
|
|
||||||
|
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',
|
||||||
|
]
|
||||||
|
|
||||||
|
ROOT_URLCONF = 'config.urls'
|
||||||
|
|
||||||
|
TEMPLATES = [
|
||||||
|
{
|
||||||
|
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||||
|
'DIRS': [],
|
||||||
|
'APP_DIRS': True,
|
||||||
|
'OPTIONS': {
|
||||||
|
'context_processors': [
|
||||||
|
'django.template.context_processors.request',
|
||||||
|
'django.contrib.auth.context_processors.auth',
|
||||||
|
'django.contrib.messages.context_processors.messages',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
WSGI_APPLICATION = 'config.wsgi.application'
|
||||||
|
|
||||||
|
|
||||||
|
# Database
|
||||||
|
# https://docs.djangoproject.com/en/5.2/ref/settings/#databases
|
||||||
|
|
||||||
|
DATABASES = {
|
||||||
|
'default': {
|
||||||
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
|
'NAME': BASE_DIR / 'db.sqlite3',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Password validation
|
||||||
|
# https://docs.djangoproject.com/en/5.2/ref/settings/#auth-password-validators
|
||||||
|
|
||||||
|
AUTH_PASSWORD_VALIDATORS = [
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# Internationalization
|
||||||
|
# https://docs.djangoproject.com/en/5.2/topics/i18n/
|
||||||
|
|
||||||
|
LANGUAGE_CODE = 'en-us'
|
||||||
|
|
||||||
|
TIME_ZONE = 'UTC'
|
||||||
|
|
||||||
|
USE_I18N = True
|
||||||
|
|
||||||
|
USE_TZ = True
|
||||||
|
|
||||||
|
|
||||||
|
# Static files (CSS, JavaScript, Images)
|
||||||
|
# https://docs.djangoproject.com/en/5.2/howto/static-files/
|
||||||
|
|
||||||
|
STATIC_URL = 'static/'
|
||||||
|
|
||||||
|
# Default primary key field type
|
||||||
|
# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field
|
||||||
|
|
||||||
|
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
"""
|
||||||
|
URL configuration for config project.
|
||||||
|
|
||||||
|
The `urlpatterns` list routes URLs to views. For more information please see:
|
||||||
|
https://docs.djangoproject.com/en/5.2/topics/http/urls/
|
||||||
|
Examples:
|
||||||
|
Function views
|
||||||
|
1. Add an import: from my_app import views
|
||||||
|
2. Add a URL to urlpatterns: path('', views.home, name='home')
|
||||||
|
Class-based views
|
||||||
|
1. Add an import: from other_app.views import Home
|
||||||
|
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
|
||||||
|
Including another URLconf
|
||||||
|
1. Import the include() function: from django.urls import include, path
|
||||||
|
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
||||||
|
"""
|
||||||
|
from django.contrib import admin
|
||||||
|
from django.urls import path
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path('admin/', admin.site.urls),
|
||||||
|
]
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
"""
|
||||||
|
WSGI config for config project.
|
||||||
|
|
||||||
|
It exposes the WSGI callable as a module-level variable named ``application``.
|
||||||
|
|
||||||
|
For more information on this file, see
|
||||||
|
https://docs.djangoproject.com/en/5.2/howto/deployment/wsgi/
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from django.core.wsgi import get_wsgi_application
|
||||||
|
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')
|
||||||
|
|
||||||
|
application = get_wsgi_application()
|
||||||
+14
-11
@@ -110,18 +110,21 @@ MVP 不做:
|
|||||||
统一启动与验证入口收敛到根目录 `./init.sh`(Windows 原生 PowerShell 用 `./init.ps1`)。骨架落地后,真实命令大致为:
|
统一启动与验证入口收敛到根目录 `./init.sh`(Windows 原生 PowerShell 用 `./init.ps1`)。骨架落地后,真实命令大致为:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 安装依赖(建议 uv 或 venv + pip)
|
# Windows PowerShell
|
||||||
uv sync # 或 pip install -r requirements.txt
|
py -3.12 -m pip install -r requirements.txt
|
||||||
# 数据库迁移
|
py -3.12 manage.py check
|
||||||
python manage.py migrate
|
py -3.12 manage.py test
|
||||||
# 基础验证 / 测试
|
py -3.12 manage.py runserver
|
||||||
python manage.py test
|
|
||||||
# 本地开发启动
|
# Unix / WSL
|
||||||
python manage.py runserver
|
python3.12 -m pip install -r requirements.txt
|
||||||
|
python3.12 manage.py check
|
||||||
|
python3.12 manage.py test
|
||||||
|
python3.12 manage.py runserver
|
||||||
```
|
```
|
||||||
|
|
||||||
说明:
|
说明:
|
||||||
|
|
||||||
- 改后端逻辑后跑:`python manage.py test`。
|
- 改后端逻辑后跑:`py -3.12 manage.py test`(Windows)或 `python3.12 manage.py test`(Unix/WSL)。
|
||||||
- 改数据模型后跑:`python manage.py makemigrations && python manage.py migrate && python manage.py test`。
|
- 改数据模型后跑:`makemigrations && migrate && test`;T-002 接入 MySQL 与自定义 User 前不要提前迁移。
|
||||||
- 如果命令当前不可运行(骨架未建),必须在回复里如实说明原因。
|
- 如果命令当前不可运行,必须在回复里如实说明原因。
|
||||||
|
|||||||
+12
-9
@@ -25,12 +25,12 @@
|
|||||||
| 任务队列 | 暂不引入(Celery/RQ) | 待定 | V2 异步化时再评估 |
|
| 任务队列 | 暂不引入(Celery/RQ) | 待定 | V2 异步化时再评估 |
|
||||||
| 部署方式 | Docker + Gunicorn(gthread) + Nginx,单体 | 待定 | MVP 先 `runserver`;生产 Nginx 按路径把 `/api/generate/*`(图片长请求)与用户端页面**分流到不同 gunicorn/worker 池**,避免图片阻塞拖慢页面(见 `04-architecture.md` 5.1) |
|
| 部署方式 | Docker + Gunicorn(gthread) + Nginx,单体 | 待定 | MVP 先 `runserver`;生产 Nginx 按路径把 `/api/generate/*`(图片长请求)与用户端页面**分流到不同 gunicorn/worker 池**,避免图片阻塞拖慢页面(见 `04-architecture.md` 5.1) |
|
||||||
| 测试 | Django 自带 `manage.py test`(unittest)/ 可选 pytest-django | 已定 | 先用内置 test runner,重点覆盖计费与回调 |
|
| 测试 | Django 自带 `manage.py test`(unittest)/ 可选 pytest-django | 已定 | 先用内置 test runner,重点覆盖计费与回调 |
|
||||||
| 依赖管理 | uv 或 venv + pip(`requirements.txt`) | 待定 | 二选一,骨架任务确定后写死并同步 init 脚本 |
|
| 依赖管理 | 系统 Python 3.12 + pip + `requirements.txt` | 已定 | 不使用虚拟环境;Windows 用 `py -3.12`,Unix/WSL 用 `python3.12`;命令已同步到 init 脚本 |
|
||||||
|
|
||||||
## 二、决策记录与演进
|
## 二、决策记录与演进
|
||||||
|
|
||||||
- **Django 而非 FastAPI**:核心收益是 django-admin 直接满足「运营后台」需求;FastAPI 需自建后台。代价是异步生态较弱,但 MVP 同步返回,不受影响。
|
- **Django 而非 FastAPI**:核心收益是 django-admin 直接满足「运营后台」需求;FastAPI 需自建后台。代价是异步生态较弱,但 MVP 同步返回,不受影响。
|
||||||
- **锁定 Django 5.2 LTS + Python 3.12**:① 版本红线属安全而非性能——生文/图生图瓶颈在「等上游 + worker 并发 + 超时」,不在框架版本(详见 [架构设计](04-architecture.md) 5.1),故版本选择只按安全与维护窗口定;② Django 4.0/4.1 已 EOL、无安全补丁,涉资金服务禁用;4.2 LTS 支持窗口临近尾声,不从其起步;5.2 LTS 维护到 2028,窗口最长。③ Django 5.2 支持 Python 3.10–3.13,锁 3.12 取「稳定 + 库全 + 性能」的平衡,避开 3.10(临近 EOL)与 3.14(不在 5.2 官方矩阵)。骨架任务须在 `pyproject.toml` 写死 `requires-python = ">=3.12,<3.14"`,并在 `init.sh` / `init.ps1` 校验解释器版本。
|
- **锁定 Django 5.2 LTS + Python 3.12**:① 版本红线属安全而非性能——生文/图生图瓶颈在「等上游 + worker 并发 + 超时」,不在框架版本(详见 [架构设计](04-architecture.md) 5.1),故版本选择只按安全与维护窗口定;② Django 4.0/4.1 已 EOL、无安全补丁,涉资金服务禁用;4.2 LTS 支持窗口临近尾声,不从其起步;5.2 LTS 维护到 2028,窗口最长。③ Django 5.2 支持 Python 3.10–3.13,锁 3.12 取「稳定 + 库全 + 性能」的平衡,避开 3.10(临近 EOL)与 3.14(不在 5.2 官方矩阵)。T-001 已按用户要求固定使用系统 Python 3.12:Windows PowerShell 用 `py -3.12`,Unix/WSL 用 `python3.12`。
|
||||||
- **预付费点数而非实时查支付余额**:充值时按汇率把金额转点数存本地,解耦支付系统、降低调用延迟、并发扣减用本地数据库事务即可保证。代价是需处理充值幂等与对账。
|
- **预付费点数而非实时查支付余额**:充值时按汇率把金额转点数存本地,解耦支付系统、降低调用延迟、并发扣减用本地数据库事务即可保证。代价是需处理充值幂等与对账。
|
||||||
- **稳定接口 + 可插拔供应商**:对外只 `generate text/image` 两接口 + 能力别名;具体模型在后台配置并经适配器调用。收益是换供应商对调用方零改动、计费按别名稳定、可加授权与故障转移;代价是需维护适配器层与别名映射。**调用方不绑具体模型 SKU**。
|
- **稳定接口 + 可插拔供应商**:对外只 `generate text/image` 两接口 + 能力别名;具体模型在后台配置并经适配器调用。收益是换供应商对调用方零改动、计费按别名稳定、可加授权与故障转移;代价是需维护适配器层与别名映射。**调用方不绑具体模型 SKU**。
|
||||||
- **同步生成而非任务队列**:MVP 不引入 Celery/Redis,降低复杂度;图片耗时长,靠调大超时支撑,V2 再异步化。
|
- **同步生成而非任务队列**:MVP 不引入 Celery/Redis,降低复杂度;图片耗时长,靠调大超时支撑,V2 再异步化。
|
||||||
@@ -42,18 +42,21 @@
|
|||||||
|
|
||||||
## 三、构建与运行命令
|
## 三、构建与运行命令
|
||||||
|
|
||||||
> 以下为骨架落地后的目标命令;初始化任务(T-001)完成后须用真实命令替换并同步到 `init.sh` / `init.ps1` 与 `current-state.md`。
|
> 以下为当前真实命令;Windows 原生 PowerShell 使用 `py -3.12`,Unix/WSL 使用 `python3.12`。
|
||||||
|
|
||||||
| 用途 | 命令 |
|
| 用途 | 命令 |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| 安装依赖 | `uv sync` 或 `pip install -r requirements.txt` |
|
| 安装依赖(Windows) | `py -3.12 -m pip install -r requirements.txt` |
|
||||||
| 数据库迁移 | `python manage.py makemigrations && python manage.py migrate` |
|
| 安装依赖(Unix/WSL) | `python3.12 -m pip install -r requirements.txt` |
|
||||||
| 创建后台管理员 | `python manage.py createsuperuser` |
|
| 基础检查(Windows) | `py -3.12 manage.py check` |
|
||||||
| 本地开发 | `python manage.py runserver` |
|
| 基础检查(Unix/WSL) | `python3.12 manage.py check` |
|
||||||
| 测试 | `python manage.py test` |
|
| 测试(Windows) | `py -3.12 manage.py test` |
|
||||||
|
| 本地开发(Windows) | `py -3.12 manage.py runserver` |
|
||||||
|
| 创建后台管理员 | T-003 后执行 `py -3.12 manage.py createsuperuser` |
|
||||||
|
| 数据库迁移 | T-002 接入 MySQL 后执行 `makemigrations` / `migrate` |
|
||||||
| 格式化 / 静态检查 | `ruff check .`(待定,确定后写死) |
|
| 格式化 / 静态检查 | `ruff check .`(待定,确定后写死) |
|
||||||
|
|
||||||
Windows PowerShell 命令与上相同(Django 跨平台),差异仅在依赖安装与虚拟环境激活方式,由 `init.ps1` 统一封装。
|
统一入口仍是根目录 `./init.ps1`(Windows)或 `./init.sh`(Unix/WSL)。T-001 阶段只做框架检查,不跑迁移;T-002 接入 MySQL 与自定义 User 后再启用迁移路径。
|
||||||
|
|
||||||
## 四、依赖纪律
|
## 四、依赖纪律
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
| ID | 任务 | 依赖 | 验收要点 | 状态 |
|
| ID | 任务 | 依赖 | 验收要点 | 状态 |
|
||||||
| --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- |
|
||||||
| T-001 | 初始化 Django + DRF 项目骨架 | - | `manage.py` 可运行;`runserver` 起得来;用真实命令替换 `init.sh`/`init.ps1` 与 `00-ai-start-here.md`/`03-tech-stack.md`/`current-state.md` 的占位命令 | TODO |
|
| T-001 | 初始化 Django + DRF 项目骨架 | - | `manage.py` 可运行;`runserver` 起得来;用真实命令替换 `init.sh`/`init.ps1` 与 `00-ai-start-here.md`/`03-tech-stack.md`/`current-state.md` 的占位命令 | DONE |
|
||||||
| T-002 | 建立 apps 目录、自定义 User 与配置 | T-001 | 按 `04-architecture.md` 建 `apps/users|portal|billing|ai|api`;**首次迁移前定义自定义 `User` 模型(设 `AUTH_USER_MODEL`)**;settings 用环境变量读密钥、配 MySQL(utf8mb4),无明文密钥 | TODO |
|
| T-002 | 建立 apps 目录、自定义 User 与配置 | T-001 | 按 `04-architecture.md` 建 `apps/users|portal|billing|ai|api`;**首次迁移前定义自定义 `User` 模型(设 `AUTH_USER_MODEL`)**;settings 用环境变量读密钥、配 MySQL(utf8mb4),无明文密钥 | TODO |
|
||||||
| T-003 | 接通 django-admin 与最小测试 | T-001 | `createsuperuser` 后能登录 `/admin/`;`manage.py test` 可运行(至少 1 条占位测试通过) | TODO |
|
| T-003 | 接通 django-admin 与最小测试 | T-001 | `createsuperuser` 后能登录 `/admin/`;`manage.py test` 可运行(至少 1 条占位测试通过) | TODO |
|
||||||
|
|
||||||
|
|||||||
+25
-20
@@ -12,13 +12,13 @@
|
|||||||
## 当前快照
|
## 当前快照
|
||||||
|
|
||||||
- 日期:2026-07-01
|
- 日期:2026-07-01
|
||||||
- 阶段:MVP 起步(仅文档,无代码)
|
- 阶段:Phase 0 地基,T-001 已完成;下一步 T-002
|
||||||
- 技术栈:Django 5.2 LTS + Python 3.12 + DRF + django-admin + 用户端(模板 SSR/Bootstrap/allauth) + MySQL 8.4(独立实例)(计划,未落地);详见 `03-tech-stack.md`
|
- 技术栈:系统 Python 3.12.3 + Django 5.2.15 + DRF 3.16.1 + django-admin;用户端(模板 SSR/Bootstrap/allauth) 与 MySQL 8.4 接入在后续任务落地;详见 `03-tech-stack.md`
|
||||||
- 生产代码:尚无。`cmhub/` 目前只有 `docs/` 与根级入口文档
|
- 生产代码:已有最小 Django 工程骨架:`manage.py`、`config/`
|
||||||
- 测试:尚无
|
- 测试:Django test runner 可运行,当前 0 tests
|
||||||
- 数据:AI 上游调用与模型配置参考 `D:\chengma\cmbot`(`src/services/ai_text_service.py`、`ai_image_service.py`、`config/ai_models.json`)
|
- 数据:AI 上游调用与模型配置参考 `D:\chengma\cmbot`(`src/services/ai_text_service.py`、`ai_image_service.py`、`config/ai_models.json`)
|
||||||
- 标准启动路径:`./init.sh`(待 T-001 填入真实命令后生效)
|
- 标准启动路径:Windows 用 `./init.ps1`;Unix/WSL 用 `./init.sh`
|
||||||
- 标准验证路径:`python manage.py test`(待骨架落地后生效)
|
- 标准验证路径:Windows 用 `py -3.12 manage.py check` / `py -3.12 manage.py test`
|
||||||
- 设计基线:**自助用户端 + 对外 API + 运营后台**三合一单体;用户模型 `User`(auth)/`UserWallet`(点数,锁 wallet 扣点)/`ApiKey`(1:N,哈希存储);对外两接口 + **能力别名 + Provider 适配器**(可插拔供应商);自助扫码充值;注册不送点数。详见 `04-architecture.md` 与 2026-06-29 / 2026-07-01 的 `progress.md` 决策
|
- 设计基线:**自助用户端 + 对外 API + 运营后台**三合一单体;用户模型 `User`(auth)/`UserWallet`(点数,锁 wallet 扣点)/`ApiKey`(1:N,哈希存储);对外两接口 + **能力别名 + Provider 适配器**(可插拔供应商);自助扫码充值;注册不送点数。详见 `04-architecture.md` 与 2026-06-29 / 2026-07-01 的 `progress.md` 决策
|
||||||
- 配置基线:运行环境变量集中见 `docs/env.md`;真实密钥/支付凭证不得写入代码或文档样例。充值订单在创建时锁定汇率与预计点数,回调入账使用订单值,不按新汇率重算
|
- 配置基线:运行环境变量集中见 `docs/env.md`;真实密钥/支付凭证不得写入代码或文档样例。充值订单在创建时锁定汇率与预计点数,回调入账使用订单值,不按新汇率重算
|
||||||
- 当前 blocker(已降级):**支付协议已明确**(微信 V3 native + 支付宝当面付,见 `api.md` / `04` 4.2,参考同支付系统 PHP 实现);**仅缺商户密钥/证书真实值**(微信 appid/mchid/apiv3_key/证书、支付宝 appid/公私钥、notify_url 域名)。不阻塞开发,T-304/T-305 可先 mock 联调,上线前填真实商户配置
|
- 当前 blocker(已降级):**支付协议已明确**(微信 V3 native + 支付宝当面付,见 `api.md` / `04` 4.2,参考同支付系统 PHP 实现);**仅缺商户密钥/证书真实值**(微信 appid/mchid/apiv3_key/证书、支付宝 appid/公私钥、notify_url 域名)。不阻塞开发,T-304/T-305 可先 mock 联调,上线前填真实商户配置
|
||||||
@@ -30,40 +30,45 @@
|
|||||||
| `docs/` | 已有 | 全套 harness 文档 |
|
| `docs/` | 已有 | 全套 harness 文档 |
|
||||||
| `AGENTS.md` / `CLAUDE.md` | 已有 | 仓库级入口 |
|
| `AGENTS.md` / `CLAUDE.md` | 已有 | 仓库级入口 |
|
||||||
| `progress.md` | 已有 | 执行流水,已记录多轮文档决策;后续任务继续追加 |
|
| `progress.md` | 已有 | 执行流水,已记录多轮文档决策;后续任务继续追加 |
|
||||||
| `init.sh` / `init.ps1` | 已有 | 启动验证入口(三命令占位待 T-001 替换) |
|
| `init.sh` / `init.ps1` | 已有 | 启动验证入口,已固定系统 Python 3.12 命令 |
|
||||||
| `config/`(Django 工程) | 待建 | T-001 创建 |
|
| `requirements.txt` | 已有 | Django 5.2 / DRF 3.16 依赖 |
|
||||||
|
| `config/`(Django 工程) | 已有 | T-001 创建,含 settings / urls / wsgi / asgi |
|
||||||
| `apps/`(users/portal/billing/ai/api) | 待建 | T-002 创建(含自定义 User,首迁移前定) |
|
| `apps/`(users/portal/billing/ai/api) | 待建 | T-002 创建(含自定义 User,首迁移前定) |
|
||||||
| `manage.py` | 待建 | T-001 创建 |
|
| `manage.py` | 已有 | T-001 创建 |
|
||||||
| `tests/` | 待建 | 随各任务补充 |
|
| `tests/` | 待建 | 随各任务补充 |
|
||||||
|
|
||||||
## 任务看板状态
|
## 任务看板状态
|
||||||
|
|
||||||
任务状态以 [`06-tasks.md`](06-tasks.md) 为准,历史执行记录见 [`../progress.md`](../progress.md)。
|
任务状态以 [`06-tasks.md`](06-tasks.md) 为准,历史执行记录见 [`../progress.md`](../progress.md)。
|
||||||
|
|
||||||
- 已完成:无。
|
- 已完成:T-001 初始化 Django + DRF 项目骨架。
|
||||||
- 正在进行:无。
|
- 正在进行:无。
|
||||||
- 下一个可领取任务:**T-001 初始化 Django + DRF 项目骨架**。
|
- 下一个可领取任务:**T-002 建立 apps 目录、自定义 User 与配置**。
|
||||||
|
|
||||||
## 当前可运行内容
|
## 当前可运行内容
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 骨架未建,以下命令在 T-001 完成后才可用:
|
# Windows PowerShell
|
||||||
# 本地开发
|
py -3.12 -m pip install -r requirements.txt
|
||||||
python manage.py runserver
|
py -3.12 manage.py check
|
||||||
# 测试
|
py -3.12 manage.py test
|
||||||
python manage.py test
|
py -3.12 manage.py runserver
|
||||||
# 迁移
|
|
||||||
python manage.py makemigrations && python manage.py migrate
|
# Unix / WSL
|
||||||
|
python3.12 -m pip install -r requirements.txt
|
||||||
|
python3.12 manage.py check
|
||||||
|
python3.12 manage.py test
|
||||||
|
python3.12 manage.py runserver
|
||||||
```
|
```
|
||||||
|
|
||||||
当前仓库尚无可运行代码,只有文档。
|
当前骨架可运行。T-001 暂保留 Django 默认 SQLite 配置用于框架启动检查;T-002 必须在首次迁移前创建自定义 User,并按 `env.md` 接入 MySQL 8.4 / utf8mb4。
|
||||||
|
|
||||||
## 开始编码前检查
|
## 开始编码前检查
|
||||||
|
|
||||||
1. 读仓库级 `AGENTS.md` / `CLAUDE.md`。
|
1. 读仓库级 `AGENTS.md` / `CLAUDE.md`。
|
||||||
2. 读 `docs/00-ai-start-here.md`。
|
2. 读 `docs/00-ai-start-here.md`。
|
||||||
3. 读 `docs/05-coding-rules.md`(尤其第 8 节资金安全)。
|
3. 读 `docs/05-coding-rules.md`(尤其第 8 节资金安全)。
|
||||||
4. 在 `docs/06-tasks.md` 取第一个 `TODO` 且依赖均 `DONE` 的任务(当前为 T-001)。
|
4. 在 `docs/06-tasks.md` 取第一个 `TODO` 且依赖均 `DONE` 的任务(当前为 T-002)。
|
||||||
5. 将该任务状态改为 `DOING`。
|
5. 将该任务状态改为 `DOING`。
|
||||||
|
|
||||||
## 维护规则
|
## 维护规则
|
||||||
|
|||||||
@@ -10,10 +10,10 @@
|
|||||||
$ErrorActionPreference = "Stop"
|
$ErrorActionPreference = "Stop"
|
||||||
Set-Location -Path $PSScriptRoot
|
Set-Location -Path $PSScriptRoot
|
||||||
|
|
||||||
# 依赖管理 uv / pip 二选一(03-tech-stack 标为待定);默认 pip + requirements.txt。
|
# T-001 固定使用系统 Python 3.12,不使用虚拟环境。
|
||||||
$InstallCmd = "pip install -r requirements.txt" # 或 uv sync
|
$InstallCmd = "py -3.12 -m pip install -r requirements.txt"
|
||||||
$VerifyCmd = "python manage.py test" # 基础验证 / 测试
|
$VerifyCmd = "py -3.12 manage.py check"
|
||||||
$StartCmd = "python manage.py runserver" # 开发启动
|
$StartCmd = "py -3.12 manage.py runserver"
|
||||||
|
|
||||||
function Assert-Configured {
|
function Assert-Configured {
|
||||||
param(
|
param(
|
||||||
@@ -41,9 +41,6 @@ if (-not (Test-Path "manage.py")) {
|
|||||||
Write-Host "==> 同步依赖"
|
Write-Host "==> 同步依赖"
|
||||||
Invoke-Expression $InstallCmd
|
Invoke-Expression $InstallCmd
|
||||||
|
|
||||||
Write-Host "==> 数据库迁移"
|
|
||||||
Invoke-Expression "python manage.py migrate"
|
|
||||||
|
|
||||||
Write-Host "==> 运行基础验证"
|
Write-Host "==> 运行基础验证"
|
||||||
Invoke-Expression $VerifyCmd
|
Invoke-Expression $VerifyCmd
|
||||||
|
|
||||||
|
|||||||
@@ -12,10 +12,10 @@ set -euo pipefail
|
|||||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
cd "$ROOT_DIR"
|
cd "$ROOT_DIR"
|
||||||
|
|
||||||
# 依赖管理 uv / pip 二选一(03-tech-stack 标为待定);默认 pip + requirements.txt。
|
# T-001 固定使用系统 Python 3.12,不使用虚拟环境。
|
||||||
INSTALL_CMD=(pip install -r requirements.txt) # 或 uv sync
|
INSTALL_CMD=(python3.12 -m pip install -r requirements.txt)
|
||||||
VERIFY_CMD=(python manage.py test) # 基础验证 / 测试
|
VERIFY_CMD=(python3.12 manage.py check)
|
||||||
START_CMD=(python manage.py runserver) # 开发启动
|
START_CMD=(python3.12 manage.py runserver)
|
||||||
|
|
||||||
ensure_configured() {
|
ensure_configured() {
|
||||||
local name="$1"
|
local name="$1"
|
||||||
@@ -42,9 +42,6 @@ fi
|
|||||||
echo "==> 同步依赖"
|
echo "==> 同步依赖"
|
||||||
"${INSTALL_CMD[@]}"
|
"${INSTALL_CMD[@]}"
|
||||||
|
|
||||||
echo "==> 数据库迁移"
|
|
||||||
python manage.py migrate
|
|
||||||
|
|
||||||
echo "==> 运行基础验证"
|
echo "==> 运行基础验证"
|
||||||
"${VERIFY_CMD[@]}"
|
"${VERIFY_CMD[@]}"
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
"""Django's command-line utility for administrative tasks."""
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Run administrative tasks."""
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')
|
||||||
|
try:
|
||||||
|
from django.core.management import execute_from_command_line
|
||||||
|
except ImportError as exc:
|
||||||
|
raise ImportError(
|
||||||
|
"Couldn't import Django. Are you sure it's installed and "
|
||||||
|
"available on your PYTHONPATH environment variable? Did you "
|
||||||
|
"forget to activate a virtual environment?"
|
||||||
|
) from exc
|
||||||
|
execute_from_command_line(sys.argv)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
+20
@@ -153,3 +153,23 @@
|
|||||||
- 阻塞:无。
|
- 阻塞:无。
|
||||||
- 决策:任务阶段顺序以 `06-tasks.md` 为权威,入口文档只做一致的导航摘要。
|
- 决策:任务阶段顺序以 `06-tasks.md` 为权威,入口文档只做一致的导航摘要。
|
||||||
- 下一步:仍从 T-001 初始化 Django + DRF 骨架开始。
|
- 下一步:仍从 T-001 初始化 Django + DRF 骨架开始。
|
||||||
|
|
||||||
|
## 2026-07-01 T-001 初始化 Django + DRF 项目骨架
|
||||||
|
|
||||||
|
- 状态:DONE
|
||||||
|
- 变更:
|
||||||
|
- 新增 `manage.py`、`config/` Django 工程骨架。
|
||||||
|
- 新增 `requirements.txt`,锁定 Django 5.2 系列与 DRF 3.16 系列。
|
||||||
|
- `config/settings.py` 加入 `rest_framework`,`SECRET_KEY` / `DEBUG` / `ALLOWED_HOSTS` 支持环境变量,默认仅用于本地开发。
|
||||||
|
- `init.ps1` / `init.sh` 替换为真实命令;按用户要求使用系统 Python 3.12,不使用虚拟环境。Windows 用 `py -3.12`,Unix/WSL 用 `python3.12`。
|
||||||
|
- 同步 `docs/00-ai-start-here.md`、`docs/03-tech-stack.md`、`docs/current-state.md`、`docs/06-tasks.md`、`README.md`。
|
||||||
|
- 验证:
|
||||||
|
- `py -3.12 -m pip install -r requirements.txt`:Django 5.2.15 / DRF 3.16.1 已安装。
|
||||||
|
- `py -3.12 manage.py check`:通过,0 issues。
|
||||||
|
- `py -3.12 manage.py test`:通过,当前 0 tests。
|
||||||
|
- `./init.ps1`:通过,完成依赖检查、`manage.py check`,打印启动命令。
|
||||||
|
- `C:\Python312\python.exe manage.py runserver 127.0.0.1:8765 --noreload`:端口 smoke 通过(TCP 8765 可连接),随后已停止进程。
|
||||||
|
- `bash -n init.sh`:当前机器无可用 bash/WSL,无法本机验证 Unix 脚本。
|
||||||
|
- 阻塞:无。
|
||||||
|
- 决策:T-001 不接入 MySQL、不创建自定义 User、不创建 apps 目录;这些按任务边界留给 T-002。T-001 阶段暂保留 Django 默认 SQLite 配置用于框架启动检查,T-002 必须在首次迁移前改为自定义 User + MySQL 8.4 配置。
|
||||||
|
- 下一步:领取 T-002 建立 apps 目录、自定义 User 与配置。
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
Django>=5.2,<5.3
|
||||||
|
djangorestframework>=3.16,<3.17
|
||||||
Reference in New Issue
Block a user