Guides

Python — Django, FastAPI and Flask

Running a Django, FastAPI or Flask app on Meghly — the commands that run, Celery workers, migrations and static files.

What runs

  • Python 3.14, 3.13 and 3.12.
  • Dependencies: requirements.txt, pyproject.toml (uv or Poetry) or a Pipfile — installed with the tool they belong to.
  • The version comes from .python-version, otherwise from requires-python in pyproject.toml.
.python-version
3.13

What Meghly runs

FrameworkWeb processAlso
Djangogunicorn <project>.wsgi --workers 2collectstatic in the build, migrate in the release
Django + Channelsuvicorn <project>.asgi:applicationWebSockets work
FastAPIuvicorn <module> --proxy-headers—
Flaskgunicorn <module> --workers 2—

Everywhere the port is 8080 and the address 0.0.0.0 — Meghly sets them. The server must be in your dependencies, though: gunicorn for Django and Flask, uvicorn for FastAPI.

requirements.txt
django>=5.2
gunicorn
psycopg[binary]
whitenoise

If it is none of these, set your own start command in the app's Processes — just make sure the app listens on PORT.

Django

Settings

The app runs behind an HTTPS router, so keep these in settings.py:

settings.py
import os

SECRET_KEY = os.environ["DJANGO_SECRET_KEY"]
DEBUG = os.environ.get("DJANGO_DEBUG") == "1"
ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS", "").split(",")
CSRF_TRUSTED_ORIGINS = [f"https://{h}" for h in ALLOWED_HOSTS if h]
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")

Then set DJANGO_SECRET_KEY (as a secret) and DJANGO_ALLOWED_HOSTS in Environment — the app's address and your domains, separated by commas.

Database

A linked database brings DATABASE_URL. dj-database-url reads it easily:

settings.py
import dj_database_url

DATABASES = {"default": dj_database_url.config(conn_max_age=600)}

python manage.py migrate --noinput runs by itself before every deploy, with the migration login.

Static and media files

  • Static (CSS, JS): collectstatic runs in the build. Serve the files with WhiteNoise — whitenoise.middleware.WhiteNoiseMiddleware right after SecurityMiddleware in MIDDLEWARE.
  • Media (uploads): set MEDIA_ROOT = "/app/media". Meghly keeps this folder across deploys.

Celery

With celery in the dependencies, Meghly adds a worker process: celery -A <project> worker (in FastAPI or Flask too — there with the module holding the Celery() object). With django-celery-beat, a separate beat process comes too. Link Redis or RabbitMQ to the app as the broker, then:

settings.py
CELERY_BROKER_URL = os.environ.get("REDIS_URL") or os.environ.get("RABBITMQ_URL")

FastAPI

Meghly finds the FastAPI() object and builds a command such as uvicorn main:app. If it cannot find it, Detect says so — then set the command in Processes:

text
uvicorn app.main:app --host 0.0.0.0 --port 8080 --proxy-headers

With Alembic, alembic upgrade head runs by itself before every deploy.

Flask

Flask runs on gunicorn. Meghly finds the Flask() object; failing that it assumes app:app (the app in app.py). For an app factory or another name, change the command in Processes, such as gunicorn "myapp:create_app()" --bind 0.0.0.0:8080.

When something goes wrong

What you seeCause and fix
Detect: "Add gunicorn to your requirements"Add gunicorn to requirements.txt (uvicorn for FastAPI).
DisallowedHostPut the address and domains in DJANGO_ALLOWED_HOSTS.
CSRF verification failed on formsCSRF_TRUSTED_ORIGINS and SECURE_PROXY_SSL_HEADER (see above).
No CSSAdd WhiteNoise.
Uploads disappear after a deployMEDIA_ROOT = "/app/media".

Stuck?

Talk to our engineers directly — by phone or email.

01782618248shohag.meghly@gmail.com