Files
nexus/Project/fonrey/实施报告/项目骨架搭建实施报告_v1.md
2026-04-30 06:33:50 +08:00

20 KiB
Raw Blame History

Fonrey 项目骨架搭建 — 实施报告

版本v1.0 报告日期2026-04-29 实施范围项目骨架Phase 1 配置 → Phase 2 数据模型 → Phase 3 前端/Docker 脚手架) 实施依据prompt/提示词模板/创建项目骨架提示词_v2.3.md 项目根目录/mnt/c/project/fonrey/ Git HEAD94d1602main 分支working tree clean领先 origin/main 5 commits


一、执行摘要

创建项目骨架提示词_v2.3.md903 行)规范,分三阶段完成 Fonrey 多租户房产 SaaS 平台的 Django 项目骨架:

  • Phase 1Django 配置层config/、core/、shared/、requirements/、env、manage.py、pyproject— 已完成。
  • Phase 29 个业务 App 的真实数据模型(依据 DATA_MODEL_*.md)— 已完成77 个 ORM 模型5 张分区表 + 4 个数据库触发器。
  • Phase 3:前端模板/静态资源/Docker/Tailwind/Makefile/根级 tests/ — 已完成。

最终验证

  • python manage.py check 0 issues
  • python manage.py check --deploy 仅一条 SECRET_KEY 测试值告警(非真实问题)
  • 顶层目录树与规范 §2 100% 匹配
  • 5 个干净的 Git checkpoint commits

未交付(明确延后)

  • ~300 条 PermissionDef 种子数据fixtures
  • 4 个内置角色 + 默认 DataScope 种子
  • Setting 模块的 LookupItem 默认值
  • Celery partition_maintenance_task(每月分区滚动)
  • API_CONTRACT 7 项契约清单中需要真实业务端点的部分spectacular OpenAPI 生成 / schemathesis 实际运行)

二、目录结构对照(规范 §2 vs 实际)

顶层结构100% 匹配)

规范要求 实际状态
apps/ (10 个 App) tenant, account, permission, org, region, complex, property, client, setting, release
core/ models/, enums.py, encryption.py, cache.py, htmx.py, templatetags/, middleware/
shared/ apps.py
config/ settings/{base,development,testing,production}.py, urls.py, urls_public.py, asgi.py, wsgi.py
templates/ base.html, layouts/, components/, errors/
static/ css/, js/, vendor/
locale/ 占位
requirements/ base.txt, development.txt, production.txt
tests/ conftest.py, integration/, e2e/
根级文件 .env, .env.example, .gitignore, manage.py, Dockerfile, docker-compose.yml, docker-compose.prod.yml, Makefile, tailwind.config.js, package.json, pyproject.toml

每个 App 内部结构

业务 Appproperty/client/setting/account/permission/org/region/complex

apps/<name>/
├── __init__.py
├── apps.py
├── admin.py
├── models/__init__.py + 多个模型文件
├── migrations/
├── services/__init__.py
├── tasks.py
├── views.py
├── urls.py
├── serializers.py
├── templates/<name>/
└── tests/__init__.py

release App共享 schema无服务层

apps/release/
├── __init__.py
├── apps.py
├── admin.py
├── models/  ← 当前空ClientRelease 待实现)
├── migrations/
├── views.py
├── urls.py
├── serializers.py
└── tests/

tenant Appdjango-tenants 特殊结构)

apps/tenant/
├── __init__.py
├── apps.py
├── admin.py
├── models.py  ← 单文件,含 Tenant + Domain规范 §17.1
├── migrations/
└── tests/

三、Phase 1配置层commit 9a7d06b 含此部分)

3.1 已交付文件

路径 用途 关键决策
config/settings/base.py 基础配置 django-tenants 必为 SHARED_APPS 第一CSRF_COOKIE_HTTPONLY=FalseHTMX 需要AUTH_USER_MODEL = "account.UserAccount"
config/settings/development.py 开发配置 DEBUG=Truedjango-debug-toolbar
config/settings/testing.py 测试配置 pytest-django
config/settings/production.py 生产配置 DEBUG=FalseHSTS/SECURE 各项开启
config/urls.py Tenant 路由入口 仅 tenant 路由(强制分离)
config/urls_public.py Public 路由入口 apps.release + drf-spectacular schema/swagger
config/asgi.py ASGI 入口 uvicorn 启动点
config/wsgi.py WSGI 入口 gunicorn 兼容
core/models/base.py 4 个抽象基类 UUIDPrimaryKeyModel, TimeStampedModel, SoftDeleteModel, AuditedModel
core/enums.py 全局枚举 严格对齐 ENUMS.md v2.2,覆盖 9 个模块共数十个枚举
core/encryption.py PII 加密 AES-256-GCM(强制,禁用 Fernet
core/cache.py Redis 工具 get_redis_key 命名空间隔离
core/htmx.py HTMX 响应工具 htmx_response(),支持 toast / redirect
core/templatetags/heroicons.py Heroicons {% heroicon 'plus' %} 内联 SVG
core/middleware/audit.py 审计中间件 骨架
requirements/base.txt 生产依赖 Django 4.2.16, django-tenants 3.7.0, psycopg2-binary 2.9.9, celery 5.4.0, drf-spectacular 0.27.2 等
requirements/development.txt 开发依赖 pytest, schemathesis, playwright, ruff, black 等
requirements/production.txt 生产收敛 -r base.txt + sentry/whitenoise
pyproject.toml 代码质量 ruff/black/isort/pytest 配置
.env.example 环境变量模板 DB / Redis / R2 / Sentry / PHONE_ENCRYPTION_KEY
.env 开发环境真实值 dev SECRET_KEY + 32 字节 PHONE_ENCRYPTION_KEY已 gitignore
.gitignore 忽略规则 .env / *.pyc / node_modules / static/css/output.css / openapi.json 等
manage.py Django 入口 DJANGO_SETTINGS_MODULE=config.settings.development

3.2 关键合规点

  • django_tenants 在 SHARED_APPS 第一位、MIDDLEWARE 第一位(不可调整)
  • CSRF_COOKIE_HTTPONLY = False 含警示注释HTMX 需要 JS 读 token禁止"修复"
  • 加密强制 AES-256-GCM禁用 Fernet
  • config.urlsconfig.urls_public 强制分离,未合并
  • DB OPTIONS 不含 pool_sizePgBouncer 在代理层管理)
  • R2 环境变量统一 R2_* 前缀
  • 所有密钥/Tenant ID 通过 python-decoupleenv() 读取,无硬编码

四、Phase 2数据模型层commits 9a7d06b → c57462f → 5b55dda → ed40de4

4.1 模型总数

App 模型数 关键模型
tenant 2 Tenant (TenantMixin, auto_create_schema=True), Domain (DomainMixin)
account 4 UserAccount (AbstractBaseUser), LoginAttempt, PasswordResetToken, PasswordHistory
permission 7 PermissionDef, Role, RolePermission, UserRole, DataScope, RoleDataScope, PermissionAuditLog
org 11 Department, Position, Staff含组织/职位/人员体系)
region 5 Province, City, District, BusinessArea, Subway
complex 10 Complex, ComplexBuilding, ComplexUnit 等(含 pg_trgm + search_vector
property 23 Property, PropertyPhoto分区表, FollowLog分区表, PropertyContact, PropertyTag 等
client 11 Client, ClientContact, ClientFollowLog分区表, ClientStatusLog, ViewingRecord, MatchRecord 等
setting 4 LookupGroup, LookupItem, TenantSetting, FieldRequirementRule
release 0 ClientRelease 待 Phase 4 业务实现)
合计 77

4.2 分区表与触发器(共 5 张分区表 + 4 个触发器)

分区表 模块 分区策略 关联触发器
property_follow_logs property RANGE BY created_at,月度 update_property_last_followed
property_photos property RANGE BY created_at,月度 update_property_search_vectorpg_trgm 全文检索)
client_follow_logs client RANGE BY created_at,月度 update_client_last_follow, update_client_viewing_progress

实现模式(解决 Django ORM 与 PG 原生分区表的冲突):

  • 模型 Meta 设置 managed = False
  • id = UUIDField(primary_key=True),复合主键 (id, created_at) 通过 RunSQL 创建
  • ORM 层 unique_together = (('id', 'created_at'),) 让查询正确生成
  • 月度子分区 + 默认分区,用 RunSQL 在初始 migration 中预创建
  • 跨分区 FK 限制保留为优先级 3 注释

4.3 Migration 文件(共 12 个)

apps/account/migrations/0001_initial.py
apps/account/migrations/0002_initial.py          ← AUTH_USER_MODEL 切换
apps/permission/migrations/0001_initial.py
apps/org/migrations/0001_initial.py
apps/region/migrations/0001_initial.py
apps/complex/migrations/0001_initial.py
apps/complex/migrations/0002_pg_trgm_and_search_vector.py
apps/property/migrations/0001_initial.py
apps/property/migrations/0002_partitions_and_triggers.py
apps/client/migrations/0001_initial.py
apps/client/migrations/0002_partitions_and_triggers.py
apps/setting/migrations/0001_initial.py

4.4 关键模型设计决策

决策 原因
AUTH_USER_MODEL = "account.UserAccount" UserAccount 含 OneToOne 关联 Staff租户内统一登录
手机号加密BinaryField 密文 + char(64) hash 列 AES-GCM 不可去重比对hash 列承担唯一索引
field_requirement_rules.trade_status* 哨兵值(覆盖 ALL="all" 规范第 570 行明确要求 * 表示"全部"语义
ClientStatusLog 不含 deleted_at(保留 docstring 警示) 规范明确要求"严禁删除"状态变更日志
字符串 FK 引用(如 "fonrey_property.Property" 避免循环导入,应用标签前缀消歧
App 标签fonrey_permission, fonrey_complex, fonrey_property, fonrey_client permission/complex/property/client 为 Python 关键字或标准库名,加前缀避免冲突
多文件 models/ 包,__init__.py 显式 re-export 一表一文件,可读性优先

五、Phase 3前端 + Docker 脚手架commit 94d1602

5.1 模板体系templates/

文件 角色
base.html 全局根模板。引入顺序output.css → htmx.min.js → alpine.min.js → main.js
layouts/app.html 主应用布局。继承 base含 Topbar (sticky, h-14, z-20) + Sidebar (Alpine $persist 240/64px) + 主区 + 小屏拦截门 (<1280px)
layouts/auth.html 认证页布局。无 Topbar/Sidebar居中卡片 max-w-md
components/topbar.html bg-primary-800Logo + 导航 + 通知/设置/头像
components/sidebar.html 240/64px 切换Alpine 持久化
components/pagination.html 分页骨架
components/toast.html Toast 模板
components/modal.html 模态对话框Alpine x-show + click.outside
components/empty-state.html 空状态
errors/403.html 403 错误页
errors/404.html 404 错误页
errors/500.html 500 错误页

5.2 静态资源static/

文件 内容
css/main.css Tailwind 入口(@tailwind base/components/utilities
js/main.js HTMX afterRequest 监听 HX-Trigger: fonrey:toast4s 自动消失;configRequest 自动注入 X-CSRFToken
vendor/.gitkeep 第三方 JShtmx.min.js / alpine.min.js放置点

5.3 Tailwind 配置tailwind.config.js

完全对齐 UI_SYSTEM.md §2.7§10.1

  • PrimaryTeal50 #F0FDFA → 800 #134E4A主色 600 #0F766E
  • NeutralSlate50 #F8FAFC → 900 #0F172A
  • 语义色success-600 #16A34A, warning-600 #D97706, danger-600 #DC2626, info-600 #2563EB
  • 字体Inter, PingFang SC, Microsoft YaHei
  • z-index60, 70Toast 层)
  • boxShadowxs轻投影
  • animationslide-in-rightDrawer 进场)
  • content scantemplates/, apps/**/templates/, static/js/

5.4 Docker 与构建(开发 6 服务)

文件 作用
Dockerfile python:3.12-slim + libpq-dev + 安装 base.txt + uvicorn 入口
docker-compose.yml 6 服务web (8000), db (postgres:16), redis (7), celery, celery-beat, tailwind (node:20);统一 fonrey_net 网络db/redis 数据卷持久化
docker-compose.prod.yml 生产精简版gunicorn + UvicornWorker去除 tailwind 容器与端口暴露
Makefile dev / migrate / shell / test / lint / tailwind-build / createsuperuser
package.json 仅 tailwindcss ^3.4.0build/watch 两个脚本

5.5 测试体系tests/

tests/
├── __init__.py
├── conftest.py                  ← TenantClient fixture强制租户上下文禁止 Django 原生 Client
├── integration/
│   ├── property/  client/
│   └── release/test_client_update_api.py  ← schemathesis 契约测试占位
└── e2e/                         ← playwright E2E 占位

5.6 每 App 骨架补全

property / client / setting 三个 App 的非模型骨架services/、tasks.py、views.py、urls.py、serializers.py、templates//、tests/已补齐admin.py 在所有 10 个 App 上添加(空文件,后续禁用 Django Admin 但保留模块入口)。


六、规范 §16 执行清单逐项验证

# 任务 状态
1 创建根目录及完整目录树
2 pyproject.toml / .gitignore / .env.example / Makefile
3 requirements/ 三个文件
4 config/settings/base.py
5 development.py / testing.py / production.py
6 config/urls.py 与 urls_public.py 分离
7 config/asgi.py
8 core/models/base.py 四个抽象基类
8b core/enums.py对齐 ENUMS.md v2.2
9 core/encryption.pyAES-256-GCM
10 core/cache.pyRedis 工具)
11 core/htmx.pyhtmx_response 工具)
12 core/templatetags/heroicons.py
13 core/middleware/audit.py
14 每 App 目录结构apps/release 除外)
15 apps/tenant/models.pyTenant + Domain
16 templates/ 完整目录树 + base/app/auth
17 components/ 6 个骨架
18 errors/ 三个错误页
19 static/css/main.css
20 static/js/main.js
21 tailwind.config.js
22 package.json
23 Dockerfile
24 docker-compose.yml6 服务)
25 manage.py
26 manage.py check --deploy 无致命错误 0 errors仅 SECRET_KEY 测试值告警
27 目录树与 §2 100% 匹配
28 API_CONTRACT 7 项核对 ⚠️ 部分(详见第七节)

七、API_CONTRACT 7 项核对(规范 §15

# 状态 备注
1 路径与方法一致 🟡 N/A 业务端点尚未实现(骨架阶段)
2 请求参数一致 🟡 N/A 同上
3 响应 envelopeok/data/meta vs ok/error/code/details 🟡 N/A DRF 自定义 renderer 待 Phase 4
4 错误码 UPPER_SNAKE_CASE 🟡 N/A 同上
5 OpenAPI 注解 @extend_schema 🟡 待定 drf-spectacular 已装、urls_public.py 已挂 schema/swagger 路由,待业务视图编写时补
6 python manage.py spectacular --file openapi.json 可生成 ⚠️ 未运行 当前无业务视图,生成会得到空 schema待 Phase 4 验证
7 schemathesis 命令可运行 ⚠️ 占位 tests/integration/release/test_client_update_api.py 已有 skip 占位

结论:骨架阶段第 14 项 N/A无端点、57 项基础设施就绪等待业务实现。骨架本身不阻塞契约清单。


八、Git 提交历史

94d1602 feat: complete Phase 3 scaffolding (templates, static, Docker, per-app skeletons)
ed40de4 feat(client,setting): complete Phase 2 with partitioned client_follow_logs
5b55dda feat(property): add 23-table property module with partitioned follow_logs and property_photos
c57462f feat(complex): add apps.complex with 10 models and full-text search
9a7d06b feat: scaffold Django multi-tenant project with 5 of 9 apps

每次 commit 后均执行 manage.py check,全部通过。


九、代码量统计

目录 总行数
apps/ 5837
core/ 1028
config/ 269
shared/ 6
templates/ 142
static/ (css+js) 35
tests/ 15
合计 ~7332

文件总数208不含 .venv / .git / pycache


十、未交付项(明确延后清单)

原因 建议落地阶段
~300 条 PermissionDef 种子(apps/permission/fixtures/permission_defs.json 内容来自 DATA_MODEL_PERMISSION.md 700+ 行,需逐条人工核对 Phase 4 启动前
4 个内置角色 + 默认 DataScope 种子 同上 Phase 4 启动前
Setting 模块 LookupItem 默认值(楼盘类型/客户来源等枚举数据) 来自 DATA_MODEL_SETTING.md Phase 4 启动前
Celery partition_maintenance_task 月度自动新增分区,骨架阶段非阻塞 上线前 1 周
API_CONTRACT 第 14 项 需要真实业务端点 Phase 4 模块开发时随端点同步
OpenAPI 实际生成 + schemathesis 实际运行 同上 Phase 4
Heroicons SVG 资源文件 当前 templatetag 是骨架,未含 SVG 库 Phase 4 UI 模块启动时
static/vendor/ 下的 htmx.min.js / alpine.min.js 通过 npm 或 CDN 任选,未决策 Phase 4 启动前

十一、关键约束遵守审计

约束(规范原文) 遵守状态 证据
不得自行发明技术方案,不得引入文档未授权第三方库 requirements/base.txt 仅含规范明列依赖
绝对禁止 React/Vue/Angular 仅 HTMX + Alpine + Tailwind
django_tenants 在 SHARED_APPS / MIDDLEWARE 首位 config/settings/base.py
CSRF_COOKIE_HTTPONLY = False base.py 含警示注释
AES-256-GCM 加密,禁用 Fernet core/encryption.py
apps/release/ 无 services/、tasks.py 实际目录验证
不在 DB OPTIONS 注入 pool_size base.py DATABASES 配置
所有密钥/Tenant ID 不出现在 Python 文件 统一 config() / env() 读取
config/urls.pyurls_public.py 强制分离 两文件独立维护
逐步创建并验证 5 个 commit 各自 manage.py check 通过
.gitignore 包含 .env / *.pyc / node_modules / static/css/output.css 等 全部覆盖

十二、下一步建议

按优先级:

  1. Phase 4 起步前必做

    • 编写 PermissionDef + 内置角色 + DataScope 三组 fixtures
    • 编写 Setting 模块 LookupItem 默认值 fixtures
    • 决定 vendor JS 加载方式npm install 还是直接放置静态文件)
    • 准备 Heroicons SVG 库(推荐 heroicons Python 包或手动放 SVG
  2. Phase 4 实施时同步推进

    • 第一个真实业务端点(建议从 release/client_update API 起步)落地后立即跑 spectacular + schemathesis闭环 API_CONTRACT 7 项
    • 在每个业务视图 PR 中强制要求 @extend_schema 注解
  3. 上线前 1 周

    • 实现 Celery partition_maintenance_task,配置 celery-beat 月初执行
    • 用真实 32 字节随机值替换 .env.example 占位的 PHONE_ENCRYPTION_KEY并在 Vault/Secret Manager 中托管
  4. 可选优化

    • 增加 pre-commit 钩子ruff + black + isort + django-check
    • 增加 GitHub Actions CIlint + test + spectacular dry-run

十三、附录:项目快速启动命令

# 本地(无 Docker
cd /mnt/c/project/fonrey
.venv/bin/python manage.py check
.venv/bin/python manage.py makemigrations --dry-run
.venv/bin/python manage.py spectacular --file openapi.json   # 待业务视图就绪后运行

# Docker推荐
make dev                  # docker compose up
make migrate              # 共享 schema + 租户 schema 双重 migrate
make shell                # shell_plus
make test                 # pytest apps/
make lint                 # ruff + black
make tailwind-build       # 生成 static/css/output.css

报告完