Skip to Content
CLICommand ReferenceCode Generation

Code Generation (make gen)

Django-CFG provides a unified code generation system that produces type-safe API clients for multiple platforms directly from your Django project. All generation is configured via a single generation.py file at the project root.

Quick Start

make gen # generate all targets make gen-ts # TypeScript only make gen-py # Python only make gen-go # Go only make gen-web # web targets only make gen-dry # dry run (preview, no files written) make gen-list # list all configured targets

Or directly:

python manage.py gen python manage.py gen --ts python manage.py gen --target sdk python manage.py gen --dry-run

generation.py Config File

Place generation.py at your Django project root (next to manage.py). It exports a single config object:

from pathlib import Path from django_cfg.modules.django_codegen import ( Config, OpenAPI, Centrifugo, Target, Language, TargetType, ) ROOT = Path(__file__).parent FRONTEND = ROOT.parent / "frontend" # Named path constants for readability MY_APP = FRONTEND / "apps" / "my" / "app" MY_API = MY_APP / "_lib" / "api" / "generated" MY_WS = MY_APP / "_ws" / "generated" config = Config( openapi=OpenAPI(targets=[...]), centrifugo=Centrifugo(targets=[...]), )

Convention: define named path constants before config — this makes it easy to see all output locations at a glance and avoid repetitive / "apps" / "my" / ... chains in every Target.

OpenAPI Clients

Generated from DRF ViewSets via drf-spectacular. Each Target maps a set of API groups to an output directory.

openapi=OpenAPI( targets=[ # Web frontend Target( lang=Language.TYPESCRIPT, type=TargetType.WEB, path=MY_API, groups=["profiles", "workspaces", "machines"], ), # TypeScript SDK package Target( lang=Language.TYPESCRIPT, type=TargetType.SDK, path=FRONTEND / "sdk" / "core" / "src" / "api" / "generated", groups=["machines", "workspaces"], ), # Python SDK Target( lang=Language.PYTHON, type=TargetType.SDK, path=PACKAGES / "my_sdk" / "src" / "my_sdk" / "api" / "generated", groups=["machines"], ), # Go CLI Target( lang=Language.GO, type="cli", path=SOFTWARE / "my_go" / "pkg" / "api" / "generated", groups=["system", "machines"], ), # Swift iOS Target( lang=Language.SWIFT_CODABLE, type="mobile", path=SOFTWARE / "MyApp" / "Sources" / "API" / "Generated", groups=["profiles", "machines"], ), ], go_module="github.com/myorg/myapp/pkg/api/generated", # optional ),

API Groups

Groups correspond to Django apps registered in openapi_client config (in api/config.py):

openapi_client=OpenAPIClientConfig( groups=[ OpenAPIGroupConfig(name="profiles", apps=["apps.profiles"]), OpenAPIGroupConfig(name="machines", apps=["apps.machines"]), ], )

Wildcard patterns are supported: "cfg_*" matches all groups starting with cfg_.

Auto-discovered Extensions

For projects with extension packages, use ExtensionTarget to auto-discover them:

from django_cfg.modules.django_codegen import ExtensionTarget openapi=OpenAPI( targets=[...], extensions=ExtensionTarget( lang=Language.TYPESCRIPT, frontend_path=FRONTEND / "extensions", package_pattern="ext-{name}", output_pattern="src/api/generated", group_prefix="ext_", ), ),

This scans frontend/extensions/ext-*/ and maps each to the ext_{name} API group automatically.

Centrifugo WebSocket Clients

Generated from channel definitions registered via @centrifugo_channel decorator. Output goes to app/_ws/generated/ by convention.

centrifugo=Centrifugo( targets=[ Target( lang=Language.TYPESCRIPT, type=TargetType.WEB, path=MY_WS, groups=["terminal", "ai_chat"], ), ], ),

Generated files include:

  • types.ts — TypeScript interfaces for all channel event types
  • client.ts — typed API wrapper with one method per RPC endpoint
  • rpc-client.ts — base WebSocket RPC client
  • subscriptions.ts — typed subscription helpers
  • index.ts — barrel export

Registering Channels

Channels must be registered in your Django app before generation:

# apps/terminal/channels.py from django_cfg.apps.integrations.centrifugo.decorators import centrifugo_channel from apps.terminal.models.events import TerminalEvent centrifugo_channel( name="terminal", pattern="terminal:session:{session_id}", event_type=TerminalEvent, )

And imported in apps.py:

class TerminalConfig(AppConfig): def ready(self): import apps.terminal.channels # noqa

Target Reference

FieldTypeDescription
langLanguage / PlatformTarget language: TYPESCRIPT, PYTHON, GO, SWIFT_CODABLE
typeTargetType / strTarget category: WEB, SDK, ADMIN, PACKAGES, or custom string like "mobile", "cli"
pathPathAbsolute output directory
groupslist[str]API groups to include. Supports "cfg_*" wildcards for OpenAPI
post_buildstr | NoneOptional shell command to run after copy, e.g. "pnpm build"

Config Reference

FieldTypeDescription
openapiOpenAPI | NoneOpenAPI REST client generation config
centrifugoCentrifugo | NoneCentrifugo WebSocket client generation config
sdkSDK | NoneSDK packages config
ormORM | NoneDjango → FastAPI/SQLModel ORM generation

CLI Flags

FlagDescription
--tsTypeScript targets only
--pyPython targets only
--goGo targets only
--swiftSwift targets only
--target <type>Filter by target type (web, sdk, admin, etc.)
--groups <g1> <g2>Filter to specific groups
--dry-runPreview what would be generated, no files written
--list-targetsPrint all configured targets and exit
--verboseVerbose output

Real-World Example

Full generation.py from a multi-platform project:

from pathlib import Path from django_cfg.modules.django_codegen import ( Config, OpenAPI, Centrifugo, Target, Language, TargetType, ) ROOT = Path(__file__).parent FRONTEND = ROOT.parent / "frontend" SOFTWARE = ROOT.parent.parent / "software" MY_APP = FRONTEND / "apps" / "my" / "app" MY_API = MY_APP / "_lib" / "api" / "generated" MY_WS = MY_APP / "_ws" / "generated" DOCS_API = FRONTEND / "apps" / "docs" / "app" / "_lib" / "api" / "generated" SDK_CORE = FRONTEND / "sdk" / "core" / "src" / "api" / "generated" MOBILE_API = SOFTWARE / "MyMobile" / "Sources" / "API" / "Generated" GO_API = SOFTWARE / "my_go" / "pkg" / "api" / "generated" PY_SDK = SOFTWARE / "my_sdk" / "python" / "src" / "my_sdk" / "api" / "generated" config = Config( centrifugo=Centrifugo( targets=[ Target( lang=Language.TYPESCRIPT, type=TargetType.WEB, path=MY_WS, groups=["terminal", "ai_chat"], ), ], ), openapi=OpenAPI( go_module="github.com/myorg/myapp/pkg/api/generated", targets=[ Target(lang=Language.TYPESCRIPT, type=TargetType.WEB, path=MY_API, groups=["profiles", "workspaces", "machines"]), Target(lang=Language.TYPESCRIPT, type=TargetType.WEB, path=DOCS_API, groups=["site", "reviews"]), Target(lang=Language.TYPESCRIPT, type=TargetType.SDK, path=SDK_CORE, groups=["machines", "workspaces"]), Target(lang=Language.SWIFT_CODABLE, type="mobile", path=MOBILE_API, groups=["profiles", "machines"]), Target(lang=Language.GO, type="cli", path=GO_API, groups=["system", "machines"]), Target(lang=Language.PYTHON, type=TargetType.SDK, path=PY_SDK, groups=["machines"]), ], ), )

See Also

Last updated on