Files
DjangoAdmin_FastAPI_EleVue/CLAUDE.md
T
ClaudeandClaude dbcce79536 chore: 基线提交(重构前快照)
重构前保存现有 apps/ 结构基线,供后续各阶段回滚。

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-07 09:43:18 +08:00

8.6 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

DjangoAdmin FastAPI+EleVue is a backend admin framework built with FastAPI (Python), Vue2.x + ElementUI (frontend, separate repo), and MySQL. It provides RBAC-based user/role/menu management, dictionary/config management, and CMS-like modules (notices, ads, members, etc.). The UI language and code comments are in Chinese.

Running the Application

# Install dependencies
pip install -r requirements.txt

# Run dev server (default: 127.0.0.1:8031)
python main.py

# Run via uvicorn directly
uvicorn main:app --host 127.0.0.1 --port 8031

# Docker
docker-compose up --build

Requires MySQL and Redis running. Configure connection details in .env (see .env for all variables). The database table prefix is fastapi_ (set via DB_PREFIX).

No test suite, linter, or formatter configuration exists in this project.

Architecture

Request Flow

main.py -> apps.create_app() -> registers CORS, Redis, routers, middleware, exception handlers -> all routes go through login_required dependency (except /login and /captcha) -> permission_required decorator checks node-level RBAC per endpoint -> check_demo decorator blocks write operations in demo mode.

Layered Module Pattern

Each business module (e.g., level, position, dept, role, user, menu, notice, dicts, config, etc.) follows the same 4-file pattern under apps/:

  • views/{module}.py - FastAPI router with endpoint definitions. Uses @permission_required("sys:{module}:{action}") and @check_demo decorators. Returns R.ok()/R.failed(). Endpoints that accept a body declare a Pydantic form parameter (e.g., data: PositionForm) — FastAPI parses and validates the JSON automatically before the handler runs.
  • services/{module}.py - Business logic: queries, CRUD operations, Excel import/export. Uses db.query(Model) directly with SQLAlchemy. Reads query params via request.query_params; body params arrive as already-validated Pydantic models, so services access fields via data.field or data.model_dump() (no await request.json() in service bodies).
  • forms/{module}.py - Pydantic BaseModel validation classes. Fields use Field(...) for constraints (min_length, max_length, ge, le, gt). Custom validators use @field_validator('field') raising ValueError(msg). Uniqueness checks query db.query(Model).filter(...).first() inside validators.
  • models/{module}.py - SQLAlchemy ORM model inheriting base_model (provides id, create_user, create_time, update_user, update_time, is_delete) and base_db (provides save(), save_all(), delete()). Table name uses DB_PREFIX prefix.

Request Validation

Pydantic v2 is used for all request body validation. The pattern for an endpoint:

@router.post('/add')
@permission_required("sys:level:add")
@check_demo
async def add(request: Request, data: LevelForm):
    return await level.LevelAdd(request, data)

Validation errors are caught by a global RequestValidationError handler registered in apps/__init__.py and converted to the standard response shape {"code": -1, "data": null, "msg": "field: message/..."} with HTTP 200. Services receive the validated Pydantic instance and use data.model_dump() (full dict), data.model_dump(exclude={'id'}) (for updates), or direct attribute access (data.id, data.status).

Key Directories

  • config/ - Configuration split into sub-modules: app.py (app settings, CORS, upload limits), database.py (DB connection, pool config, SQLALCHEMY_MYSQL_URL), redis.py, auth.py (JWT), captcha.py, email.py, sms.py. All loaded from .env via python-dotenv. config/__init__.py loads .env first, then re-exports everything.
  • extensions/ - Framework extensions: SQLAlchemy engine/session/contextvars (extensions/sqlalchemy.py), custom exception class (extensions/exception.py), get_db_session() accessor.
  • routers/v1.py - Central route registration. All module routers are included here with prefix paths.
  • apps/middleware/ - login_required (JWT auth dependency, ignores /login and /captcha), permission_required (decorator checking user's permission nodes; admin userId=1 bypasses all checks), check_demo (decorator that blocks write operations when FASTAPI_DEMO=True), db_session (Starlette middleware setting request-scoped DB session via contextvars).
  • utils/ - response (JSON response helpers: R.ok(), R.failed()), jwt (JWT create/parse/refresh/blacklist with HS256), password (bcrypt-based password hashing with salt), security (get_user_id(request), get_username(request) — reads from request.state set by login_required), request (parse_batch_ids, like_escape, like_contains for safe LIKE queries), captcha (verification code generation), file (file operations), redis_ctx (Redis connection pool lifecycle and request-scoped context via get_redis()), ip, formatter, rich_text.
  • apps/constants/ - constants.py (enum dicts for gender, dept types, menu types, etc.), message.py (default page size, messages, SERIALIZE_EXCLUDE_FIELDS).

Database Access

Database sessions are request-scoped via contextvars + Starlette middleware (apps/middleware/db_session.py). Services call db = get_db_session() to get the current request's session. Models use self.save() / self.delete() from base_db. The middleware auto-closes the session after each request (with rollback). Soft deletes via is_delete flag (0=active, 1=deleted).

Redis Access

Redis uses async client via utils/redis_ctx.py. Connection pool created in redis_lifespan (app lifespan), injected per-request via redis_middleware into contextvars. Business code calls get_redis() to get the current request's async Redis client.

Authentication & Authorization

  • JWT tokens via utils/jwt.py (HS256, configurable expiry via JWT_EXPIRE_MINUTES, secret via JWT_SALT env var). Token sent as Authorization: Bearer <token> header. Supports token refresh and blacklist (logout) via Redis.
  • login_required is a FastAPI Depends applied globally to the v1 router. On success, it sets request.state.user_id, request.state.username, request.state.realname.
  • permission_required is a per-endpoint decorator checking permission strings like "sys:level:list". User ID 1 (admin) bypasses all permission checks.
  • check_demo is a per-endpoint decorator that returns R.failed("演示环境,暂无操作权限") when FASTAPI_DEMO=True. Apply it after @permission_required on all write endpoints (add, update, delete, status, import, export).

API Response Format

All endpoints return JSONResponse via R.ok() or R.failed():

{"code": 0, "data": ..., "msg": "操作成功", "ok": true}   // success
{"code": -1, "data": null, "msg": "错误信息", "ok": false}  // failure

R.ok() supports **kwargs for extra fields (e.g., R.ok(data=result, count=total) adds a count field).

Pagination Pattern

List endpoints read pageNo and pageSize from request.query_params, defaulting to page 1 and PAGE_SIZE (10). Services use SQLAlchemy .limit(limit).offset((page - 1) * limit).all() and return R.ok(data=result, count=count).

Delete Pattern

Single delete: DELETE /delete/{id} where id can be comma-separated (e.g., "1,2,3"). Batch delete: DELETE /batchDelete with JSON body [1, 2, 3], parsed via parse_batch_ids(request). Both use soft delete (set is_delete = 1).

Adding a New Module

  1. Create apps/models/{name}.py - model class inheriting base_model and base_db, set __tablename__ = DB_PREFIX + "{name}"
  2. Create apps/forms/{name}.py - Pydantic BaseModel validation classes with Field(...) constraints and @field_validator for custom checks
  3. Create apps/services/{name}.py - CRUD service functions following the get_level_page/get_level_detail/add_level/update_level/delete_level/update_level_status pattern
  4. Create apps/views/{name}.py - APIRouter with endpoints, apply @permission_required and @check_demo on write endpoints
  5. Register the router in routers/v1.py - v1.include_router({name}.router, prefix="/{prefix}", tags=["标签"])
  6. Import the view in routers/v1.py

Key Dependencies

  • FastAPI 0.140.0, Uvicorn 0.51.0
  • SQLAlchemy 2.0.51 (declarative style with declarative_base(), not 2.0 mapped_column style)
  • PyMySQL 1.2.0, Redis 8.0.1 (async), PyJWT 2.13.0
  • Pydantic 2.13.4 (for request validation via BaseModel + Field + field_validator), openpyxl (for Excel import/export)
  • python-dotenv for .env loading, bcrypt for password hashing, Pillow for captcha generation