← Back to Blog

Django gets first-class treatment in v0.13.0

·8 min read

Django was always supported; it was never respected. The old flow asked you to run manage.py runserver yourself while a separate watcher process regenerated types, and the config had no way to express “this is where registration happens.” v0.13.0 fixes all three: pyrpc dev launches runserver for you, the entry point is honestly a path to manage.py, and a required types_module names your registration module.

Diagram: views.py declares procedures, urls.py imports views and mounts, pyrpc dev runs manage.py runserver

The three files that matter

# myproject/views.py, where procedures live (your types_module)
from pyrpc_core import rpc

@rpc.query
def greet(name: str = "World") -> str:
 return f"Hello, {name}!"
# myproject/urls.py, wiring
from . import views # <- REQUIRED: executes the decorators
urlpatterns = [path("admin/", admin.site.urls)]
mount_django(urlpatterns) # appends POST /rpc and GET /rpc

The import in urls.py is not style, it is the registration mechanism. Miss it and /rpc serves an empty schema with no error anywhere.

One command from server/

$ cd server && pyrpc dev --yes --framework django --client ../client

 django manage.py client=../client
 ✓ pyrpc.json created (auto-configured)
 ✓ types generated (1 procs) → ../client/__pyrpc.ts
 pyRPC dev http://127.0.0.1:8000/rpc

Behind that banner, the process tree is Django’s own:

python manage.py runserver 127.0.0.1:8000 # cwd = manage.py's directory

# pyrpc.json
{ "backend": { "framework": "django",
 "entrypoint": "manage.py",
 "types_module": "myproject.views" } }
  • Interactive mode asks for the manage.py path and offers the shallowest */views.py as the preselected types module.
  • Omitting types_module fails loudly at startup with instructions, because guessing wrong produces an empty schema silently.
  • --noreload handling: when you run dev with reload disabled, the flag maps to runserver’s native spelling.

Why this fixes stale-type regen too

Editing views.py triggers codegen, which imports myproject.views. Because that import executes the decorators against a reloaded module, the router reflects your edit immediately, no cached-importer staleness. Under the old model (importing the entrypoint), urls.py stayed cached and its from . import views never re-ran, so edits could regenerate yesterday’s schema with a green checkmark.

Frontend unchanged

Same links-based client as every other backend:createNextClient<Types>{ links: [httpBatchLink({ url })] }. Your React/Vue/Svelte/Next code cannot tell Django from FastAPI, which is the point.