7.5 KiB
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
Viewclasses), MySQL, Redis, JWT auth. All in Python underapplication/. - 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 ...).
python manage.py runserver # http://127.0.0.1:8000
python manage.py makemigrations <app> && 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)
python generator.py django_<table> # parse DB table -> config.json -> generate module + Vue + menus
python generator.py django_<table> --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/)
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)
generator.py—TableSchemaParserintrospects 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-inconfig.json.generator_config.py—CodeGeneratorconsumes that config, renders Jinja2 templates frompublic/templates/(e.g.*.py.tpl,ui/*.vue.tpl), and writes:- backend module files under
application/<module>/(models/forms/services/views/urls/admin/apps + a migration), - Vue files under
ui/src/views/...and an API module underui/src/api/tool/<module>.ts, - then runs
makemigrations/migrate, inserts menu + permission nodes into the DB (application.menu.models.Menu), and appends the route toapplication/urls.pyand the app toINSTALLED_APPSinapplication/settings.py.
- backend module files under
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/<module>/ follows the same generated layout:
models.py— inherits abstractBaseModel(application/models.py):id, create_user, create_time, update_user, update_time, is_delete. All queries filteris_delete=False(soft delete).forms.py— DjangoModelFormwith per-field validation and Chineseerror_messages.services.py— all business logic lives here, in functions likeget_<m>_page,add_<m>,update_<m>,delete_<m>(batch delete via comma-joined IDs),update_<m>_status. Usesparse_request_body+regular.get_errfromutils/. Pagination via DjangoPaginator; response shape{records, total, size, current, pages}.views.py— one class per endpoint, each@method_decorator(check_login, name="<method>"), subclassingPermissionRequiredwithpermission_required = ("sys:<module>:<action>",), and write/read handlers decorated with@operation_log(title=..., log_type=LogType.<X>)fromapplication/operation_log/decorators.py.urls.py— declared per-module, wired intoapplication/urls.py(each path is a module prefix likelevel/,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 theAuthorization: Bearer <token>JWT (parsed byutils/jwts.py);ignoreURL = ['/login', '/captcha'].PermissionRequired(middleware/permission_middleware.py) — user id 1 is superadmin (bypass), otherwise checks thesys:<module>:<action>node againstapplication/menu/services.get_user_permissions(user_id).- Frontend hides/disable buttons with the
v-permdirective using the samesys:...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) callsGET /index/getMenus, and the returned menu tree becomes Vue Router records +<el-menu>items. Each menu row'scomponentfield must match a.vueundersrc/views/**(resolved viaimport.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/<domain>/<name>.ts, importinghttpfrom@/utils/http/axios(base/api, JWT header injection, unwraps{code, data, msg}). Seesrc/api/tool/example.tsfor the canonical CRUD shape. - A generated CRUD view is a folder
src/views/<domain>/<entity>/withindex.vue(searchBasicFormviauseForm+querySchemas.ts, listBasicTable+columns.ts,TableActionrow buttons), plus lazy-loadededit.vue/detail.vuedialogs. Shared components:BasicTable,BasicForm,PageWrapperfromsrc/components/. Store: Pinia insrc/store/modules/(notablyasyncRoute.ts,user.ts). - Dev networking: Vite on 8001 proxies
/apito 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 insettings.pyINSTALLED_APPSand add its routes toapplication/urls.py. - Permissions are
sys:<module>:<action>for actionspage/list/detail/add/update/delete/status.