Files
mizan/packages/mizan-django
Ryth Azhur c20de182e1 Two-stage codegen: React + Vue + Svelte from one schema
Stage 1 (framework-agnostic):
  types.ts           — OpenAPI interfaces
  contexts/<name>.ts — fetchXxxContext(params) using mizanFetch
  mutations/<name>.ts — callXxx(args) using mizanCall
  functions/<name>.ts — callXxx(args) using mizanCall
  index.ts           — re-exports

Stage 2 (per framework):
  react.tsx  — hooks + context providers + SSR hydration
  vue.ts     — composables with provide/inject + ref/computed
  svelte.ts  — writable/derived store factories

New packages:
  mizan-runtime — the kernel (~200 lines, zero framework deps)
    configure(), initSession(), registerContext(), invalidate(),
    mizanFetch(), mizanCall(), MizanError
  mizan-vue     — Vue adapter (package.json, codegen template)
  mizan-svelte  — Svelte adapter (package.json, codegen template)

CLI: mizan-generate --target react,vue,svelte
Config: target: 'react' (default) in django.config.mjs

Verified: codegen produces 33 functions across 2 contexts,
14 plain functions, 0 mutations, generating all three Stage 2
outputs from one schema fetch.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 12:09:35 -04:00
..

mizan (Python)

Django server functions framework. See the monorepo root for full documentation.

Install

uv add "mizan[channels,allauth] @ git+https://git.impactsoundworks.com/isw/mizan.git#subdirectory=django"

Setup

# settings.py
INSTALLED_APPS = ["mizan", ...]

# urls.py
path("api/mizan/", include("mizan.urls"))

# asgi.py (optional, for WebSocket)
from mizan import wrap_asgi
application = wrap_asgi(get_asgi_application())

Define Functions

from mizan.client import client
from mizan.setup.registry import register
from pydantic import BaseModel

class Output(BaseModel):
    message: str

@client
def echo(request, text: str) -> Output:
    return Output(message=text)

register(echo, "echo")

Register in apps.py:

def ready(self):
    import myapp.mizan_clients

Auth

@client(auth=True)          # requires authentication
@client(auth='staff')       # requires is_staff
@client(auth='superuser')   # requires is_superuser
@client(auth=my_callable)   # custom check

Contexts

@client(context='global')   # fetched once, SSR-hydrated, becomes useCurrentUser()
@client(context='local')    # fetched with params, becomes <GreetProvider>

Forms

from mizan.forms import mizanFormMixin, mizanFormMeta

class ContactForm(mizanFormMixin, forms.Form):
    mizan = mizanFormMeta(name="contact", title="Contact Us")
    name = forms.CharField()
    email = forms.EmailField()

    def on_submit_success(self, request):
        return {"sent": True}

Auto-registers contact.schema, contact.validate, contact.submit. Generates useContactForm() with Zod validation.

Channels

from mizan.channels import ReactChannel

class ChatChannel(ReactChannel):
    class Params(BaseModel):
        room: str
    class DjangoMessage(BaseModel):
        text: str

    def authorize(self, params):
        return self.user.is_authenticated
    def group(self, params):
        return f"chat_{params.room}"

Generates useChatChannel({ room }).

Running Tests

uv sync --extra dev --extra channels
uv run pytest