- Write a Django site in a single file, using views, models and admin
- Run it locally or in production, or share it as a standalone script
- Automatically convert it to a full Django project when you're ready for it to grow
Install nanodjango:
pip install nanodjango
Write your app in single .py
file - for example:
from django.db import models
from nanodjango import Django
app = Django()
@app.admin
class CountLog(models.Model):
# Standard Django model, registered with the admin site
timestamp = models.DateTimeField(auto_now_add=True)
@app.route("/")
def count(request):
# Standard Django function view
CountLog.objects.create()
return f"<p>Number of page loads: {CountLog.objects.count()}</p>"
@app.api.get("/add")
def add(request):
# Django Ninja API support built in
CountLog.objects.create()
return {"count": CountLog.objects.count()}
@app.route("/slow/")
async def slow(request):
import asyncio
await asyncio.sleep(10)
return "Async views supported"
Save that as counter.py
, then set it up and run it:
nanodjango run counter.py
This will create migrations and a database, and run your project in development mode.
- See Command usage for more options
If your project outgrows its single file, you can convert it into a full Django site:
nanodjango counter.py convert path/to/site --name=counter
- See Converting to a full Django project for more information
Nanodjango apps are great for sharing examples and prototypes.
Add inline script metadata at the top with your dependencies:
# /// script
# dependencies = ["nanodjango"]
# ///
and call app.run()
at the bottom:
if __name__ == "__main__":
app.run()
Now your app can be run without installing anything, using uv
or pipx
:
# Run with uv
uv run ./script.py
# or with pipx
pipx run ./script.py
You can still manually install dependencies and run the script directly with Python:
pip install nanodjango
python script.py
Anything you would normally do with manage.py
you can do with nanodjango manage
:
nanodjango manage script.py check
nanodjango manage script.py makemigrations script
nanodjango manage script.py runserver 0:8000
Run it using nanodjango serve
:
nanodjango serve counter.py
This will use gunicorn, or uvicorn if you have async views.
Alternatively, you can pass the app directly to a WSGI or ASGI server if you prefer:
gunicorn -w 4 counter:app
uvicorn counter:app
- See Command usage for more options
For more details, see