Skip to Content

Advanced Topics

Advanced configuration and usage patterns for production environments.


Groups (API Organization)

Groups allow you to organize large APIs into logical units. Each group generates separate clients.

Why Use Groups?

Benefits:

  • âś… Separate clients for different teams/features
  • âś… Smaller bundle sizes (import only what you need)
  • âś… Clear API boundaries
  • âś… Independent versioning
  • âś… Reduced compilation time

Basic Configuration

# api/config.py from django_cfg import OpenAPIClientConfig, OpenAPIGroupConfig openapi_client = OpenAPIClientConfig( enabled=True, output_dir="openapi", groups=[ OpenAPIGroupConfig( name="core", apps=["users", "accounts", "profiles"], title="Core API", description="User management and authentication", version="1.0.0", ), OpenAPIGroupConfig( name="billing", apps=["payments", "subscriptions", "invoices"], title="Billing API", description="Payment processing", version="1.0.0", ), OpenAPIGroupConfig( name="content", apps=["blog", "cms", "media"], title="Content API", description="Content management", version="1.0.0", ), ], )

Output Structure

openapi/ ├── core/ # Group: core │ ├── typescript/ │ │ ├── cfg__accounts/ │ │ ├── cfg__profiles/ │ │ ├── client.ts │ │ └── index.ts │ └── python/ │ ├── client.py │ └── models/ │ ├── billing/ # Group: billing │ ├── typescript/ │ └── python/ │ ├── content/ # Group: content │ ├── typescript/ │ └── python/ │ └── archive/ # Version history └── 2025-01-15_10-00-00/

Monorepo Support

Perfect for monorepos with multiple frontends:

groups=[ # Web application OpenAPIGroupConfig( name="web", apps=["users", "billing", "content"], title="Web API", ), # Mobile application (smaller API surface) OpenAPIGroupConfig( name="mobile", apps=["users", "content"], # No billing title="Mobile API", ), # Admin panel (internal APIs) OpenAPIGroupConfig( name="admin", apps=["users", "billing", "admin", "analytics"], title="Admin API", ), ]

Generate Specific Groups

# Generate all groups python manage.py generate_api # Generate specific groups only python manage.py generate_api --groups core,billing

Archive System

Maintains version history of all generated clients.

Configuration

OpenAPIClientConfig( enabled=True, # Archive settings archive_enabled=True, archive_dir="openapi/archive", archive_max_versions=10, # Keep last 10 versions )

Archive Structure

openapi/archive/ ├── 2025-01-15_10-00-00/ │ ├── core/ │ │ ├── typescript/ │ │ └── python/ │ └── billing/ │ ├── typescript/ │ └── python/ │ ├── 2025-01-15_11-00-00/ │ └── ... │ └── 2025-01-15_12-00-00/ └── ...

Use Cases

1. Compare Changes:

# Compare two versions diff -r openapi/archive/2025-01-15_10-00-00/core/typescript \ openapi/archive/2025-01-15_11-00-00/core/typescript

2. Rollback:

# Rollback to previous version cp -r openapi/archive/2025-01-15_10-00-00/core/* openapi/core/

3. Track API Evolution:

# View history ls -lt openapi/archive/

CI/CD Integration

GitHub Actions

Automatically generate clients on API changes:

# .github/workflows/generate-api-clients.yml name: Generate API Clients on: push: paths: - 'backend/**' - 'api/**' jobs: generate: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Set up Python uses: actions/setup-python@v4 with: python-version: '3.12' - name: Install dependencies run: | pip install -r requirements.txt - name: Generate API clients run: | python manage.py generate_api - name: Commit generated clients run: | git config user.name "GitHub Actions" git config user.email "[email protected]" git add openapi/ git commit -m "chore: update API clients [skip ci]" || exit 0 git push

GitLab CI

# .gitlab-ci.yml generate-clients: stage: build image: python:3.12 script: - pip install -r requirements.txt - python manage.py generate_api artifacts: paths: - openapi/ expire_in: 30 days only: changes: - backend/** - api/**

Pre-commit Hook

Automatically generate clients before commit:

# .git/hooks/pre-commit #!/bin/bash # Generate API clients python manage.py generate_api # Add generated files git add openapi/ echo "âś… API clients regenerated"

Docker Integration

Build-time Generation

Generate clients during Docker build:

FROM python:3.12 WORKDIR /app # Install dependencies COPY requirements.txt . RUN pip install -r requirements.txt # Copy project COPY . . # Generate API clients during build RUN python manage.py spectacular --file openapi.yaml && \ python manage.py generate_api CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]

Multi-stage Build

# Stage 1: Generate clients FROM python:3.12 AS generator WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt COPY . . RUN python manage.py generate_api # Stage 2: Runtime FROM python:3.12-slim WORKDIR /app COPY --from=generator /app/openapi /app/openapi COPY . . CMD ["python", "manage.py", "runserver"]

Multiple Environments

Generate different clients for different environments:

# config/dev.py openapi_client = OpenAPIClientConfig( enabled=True, output_dir="openapi", drf_title="My API (Development)", groups=[ OpenAPIGroupConfig( name="all", apps=["users", "accounts", "billing", "admin"], # All APIs ), ], ) # config/prod.py openapi_client = OpenAPIClientConfig( enabled=True, output_dir="openapi", drf_title="My API (Production)", groups=[ OpenAPIGroupConfig( name="public", apps=["users", "accounts", "billing"], # No admin ), ], )

Custom Output Directories

Generate clients to custom locations:

OpenAPIClientConfig( groups=[ OpenAPIGroupConfig( name="web", apps=["users", "billing"], # Custom output for TypeScript typescript_output="../../apps/web/src/api/generated", # Custom output for Python python_output="../../services/api-client", ), ], )

Workspace Integration (pnpm/yarn/npm workspaces)

For monorepo workspaces:

// package.json (root) { "workspaces": [ "apps/*", "packages/*" ] }

Generate to workspace package:

OpenAPIGroupConfig( name="shared", apps=["users", "billing"], typescript_output="../../packages/api-client/src", )

Then use in apps:

// apps/web/package.json { "dependencies": { "@mycompany/api-client": "workspace:*" } }

Performance Optimization

Parallel Generation

TypeScript and Python generated concurrently:

# Built-in parallel generation (automatic) python manage.py generate_api

Incremental Generation (Future)

Only regenerate changed groups:

# Only regenerate core group python manage.py generate_api --groups core

Caching

Template caching is enabled by default:

# Jinja2 templates compiled once jinja_env = Environment( cache_size=400 # Cache 400 compiled templates )

Custom Templates (Advanced)

Override default templates:

# custom_generator.py from django_cfg.modules.django_client.core.generator.typescript import TypeScriptGenerator class CustomTypeScriptGenerator(TypeScriptGenerator): def __init__(self, context, config): super().__init__(context, config) # Add custom template directory self.jinja_env.loader = ChoiceLoader([ FileSystemLoader('my_templates'), # Custom first FileSystemLoader('default_templates') # Fallback ])

Best Practices

1. Commit Generated Code

Always commit generated clients to version control:

git add openapi/ git commit -m "Update API clients"

This ensures:

  • Frontend and backend stay in sync
  • Easy code review of API changes
  • No runtime generation needed

2. Use Groups for Large APIs

Split large APIs:

groups=[ OpenAPIGroupConfig(name="core", apps=["users", "auth"]), OpenAPIGroupConfig(name="billing", apps=["payments"]), OpenAPIGroupConfig(name="content", apps=["blog", "media"]), ]

3. Automate Generation

Add to CI/CD pipeline:

- name: Generate clients run: python manage.py generate_api

4. Archive Old Versions

Enable archiving for version history:

OpenAPIClientConfig( archive_enabled=True, archive_max_versions=10, )

5. Validate Generated Code

Run type checkers:

# TypeScript cd frontend && pnpm tsc --noEmit # Python cd backend && mypy api_client/

Troubleshooting

See Troubleshooting for common issues and solutions.


Next Steps