# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## What this is DjangoAdmin (Django + EleVue) is a **low-code admin framework**: a full CRUD module — Django app, Vue view, API module, menu & permission records — is *generated from a database table definition*, not hand-written. The code generator is the heart of the project; the `application/example/` module and `config.json` at the repo root are samples of its output. - Backend: Django 6.0.3 + DRF (installed, but views are plain Django `View` classes), MySQL, Redis, JWT auth. All in Python under `application/`. - Frontend: Vue 3 + TypeScript + Element Plus + Pinia + Vite, in `ui/`. Derived from the vben-admin architecture. - Both sides are heavily documented in Chinese docstrings/comments; code identifiers and API field names are English. ## Commands ### Backend (repo root) Dependencies: `requirements.txt` is **UTF-16LE encoded** — `pip install -r requirements.txt` may fail on some platforms; re-save it as UTF-8 first if so. MySQL and Redis must be running; all connection settings live in `.env` (loaded by `config/env.py`, imported everywhere as `from config.env import ...`). ```bash python manage.py runserver # http://127.0.0.1:8000 python manage.py makemigrations && python manage.py migrate python manage.py test python manage.py add_full_comments # custom command: backfill DB field comments ``` `application/settings.py` hardcodes `DEBUG = True`; switch behavior via `.env` values (e.g. `DJANGO_DEMO=True` blocks all write endpoints with a demo message). ### Code generator CLI (repo root) ```bash python generator.py django_ # parse DB table -> config.json -> generate module + Vue + menus python generator.py django_
--dry-run # only print config (add --output config.json to save it) python generator.py --config config.json # generate code from an existing config file ``` Equivalent web UI exists at `/generator` (the `application/generator` app). Backend code runs `python generator.py ...` from the repo root with the venv active. ### Frontend (`ui/`) ```bash cd ui pnpm install # (package.json also aliases this as "bootstrap") pnpm dev # http://localhost:8001; proxies /api -> http://127.0.0.1:8000/ (see ui/.env.development) pnpm build # prod build pnpm type:check # vue-tsc --noEmit pnpm lint:eslint && pnpm lint:prettier && pnpm lint:stylelint ``` ## Architecture ### The code generator (read these three to understand the whole project) 1. `generator.py` — `TableSchemaParser` introspects a MySQL table (field type/comment/length/index) and heuristically classifies fields (image, rich-text, status, sort, code, filterable, choices) into a JSON "config" like the checked-in `config.json`. 2. `generator_config.py` — `CodeGenerator` consumes that config, renders Jinja2 templates from `public/templates/` (e.g. `*.py.tpl`, `ui/*.vue.tpl`), and writes: - backend module files under `application//` (models/forms/services/views/urls/admin/apps + a migration), - Vue files under `ui/src/views/...` and an API module under `ui/src/api/tool/.ts`, - then runs `makemigrations`/`migrate`, inserts menu + permission nodes into the DB (`application.menu.models.Menu`), and **appends the route to `application/urls.py` and the app to `INSTALLED_APPS` in `application/settings.py`**. 3. `application/generator/` — web endpoint wrapper around the same logic (`services.generate_tables`). Adding a table → config → generated module is the normal way new features are built; don't hand-write a full module unless you need custom logic. ### Backend module pattern Every app under `application//` follows the same generated layout: - `models.py` — inherits abstract `BaseModel` (`application/models.py`): `id, create_user, create_time, update_user, update_time, is_delete`. **All queries filter `is_delete=False`** (soft delete). - `forms.py` — Django `ModelForm` with per-field validation and Chinese `error_messages`. - `services.py` — **all business logic lives here**, in functions like `get__page`, `add_`, `update_`, `delete_` (batch delete via comma-joined IDs), `update__status`. Uses `parse_request_body` + `regular.get_err` from `utils/`. Pagination via Django `Paginator`; response shape `{records, total, size, current, pages}`. - `views.py` — one class per endpoint, each `@method_decorator(check_login, name="")`, subclassing `PermissionRequired` with `permission_required = ("sys::",)`, and write/read handlers decorated with `@operation_log(title=..., log_type=LogType.)` from `application/operation_log/decorators.py`. - `urls.py` — declared per-module, wired into `application/urls.py` (each path is a module prefix like `level/`, `dict/item/`, `role/menu/`). Convention: DB/field names are snake_case; JSON payloads use camelCase (`create_user` ↔ `createUser`). Views/services build dicts manually per record. ### Auth & permissions - `check_login` (`middleware/login_middleware.py`) validates the `Authorization: Bearer ` JWT (parsed by `utils/jwts.py`); `ignoreURL = ['/login', '/captcha']`. - `PermissionRequired` (`middleware/permission_middleware.py`) — user id **1 is superadmin (bypass)**, otherwise checks the `sys::` node against `application/menu/services.get_user_permissions(user_id)`. - Frontend hides/disable buttons with the `v-perm` directive using the same `sys:...` codes. ### Response convention `utils/R.py` — every endpoint returns `R.ok(...)` / `R.failed(...)`, envelope `{code: 0/1, data, msg, ok}`. Read it before writing a view. ### Frontend (`ui/`) - **Routes and menus are dynamic, driven by the backend.** On login the router guard (`src/router/router-guards.ts` → `generator-routers.ts`) calls `GET /index/getMenus`, and the returned menu tree becomes Vue Router records + `` items. Each menu row's `component` field must match a `.vue` under `src/views/**` (resolved via `import.meta.glob`). So new pages appear by inserting a menu row in the DB, **not** by editing a frontend route file. - API modules live under `src/api//.ts`, importing `http` from `@/utils/http/axios` (base `/api`, JWT header injection, unwraps `{code, data, msg}`). See `src/api/tool/example.ts` for the canonical CRUD shape. - A generated CRUD view is a folder `src/views///` with `index.vue` (search `BasicForm` via `useForm` + `querySchemas.ts`, list `BasicTable` + `columns.ts`, `TableAction` row buttons), plus lazy-loaded `edit.vue` / `detail.vue` dialogs. Shared components: `BasicTable`, `BasicForm`, `PageWrapper` from `src/components/`. Store: Pinia in `src/store/modules/` (notably `asyncRoute.ts`, `user.ts`). - Dev networking: Vite on 8001 proxies `/api` to Django 127.0.0.1:8000 (`.env.development`); change backend target there. ## Conventions to follow - Every source file begins with a long Chinese copyright banner from 小蚂蚁云团队 — keep it on new files (including generator output). - Docs/comments are in Chinese; identifiers, APIs, and commit-adjacent names in English. - New modules should be produced through the generator where possible; if writing one by hand, mirror `application/example/` exactly (models/forms/services/views/urls) and remember to register the app in `settings.py` `INSTALLED_APPS` and add its routes to `application/urls.py`. - Permissions are `sys::` for actions `page/list/detail/add/update/delete/status`.