diff --git a/docs/1-getting-started/settings.rst b/docs/1-getting-started/settings.rst index dfdccc7cc9..b5abf271fd 100644 --- a/docs/1-getting-started/settings.rst +++ b/docs/1-getting-started/settings.rst @@ -72,6 +72,7 @@ BREVO_API_KEY BREVO_API_KEY n/a BREVO_API_URL n/a n/a "https://api.brevo.com/v3/" SPARKPOST_API_KEY SPARKPOST_API_KEY n/a raises error SPARKPOST_API_URL n/a n/a "https://api.sparkpost.com/api/v1" +n/a PRODUCTION_PROCESSES n/a a configured dictionary depending on your choices - check settings/production.py ======================================= =========================== ============================================== ====================================================================== -------------------------- diff --git a/docs/2-local-development/developing-locally.rst b/docs/2-local-development/developing-locally.rst index c6f052ea75..9d8e8a190a 100644 --- a/docs/2-local-development/developing-locally.rst +++ b/docs/2-local-development/developing-locally.rst @@ -65,7 +65,7 @@ Make sure to have the following on your host: #. If you're running synchronously, see the application being served through Django development server: :: - uv run python manage.py runserver 0.0.0.0:8000 + uv run python manage.py devserver 0.0.0.0:8000 or if you're running asynchronously: :: diff --git a/{{cookiecutter.project_slug}}/Procfile b/{{cookiecutter.project_slug}}/Procfile index 6424e048d3..43657d99c6 100644 --- a/{{cookiecutter.project_slug}}/Procfile +++ b/{{cookiecutter.project_slug}}/Procfile @@ -1,10 +1,6 @@ release: python manage.py migrate -{%- if cookiecutter.use_async == "y" %} -web: gunicorn config.asgi:application -k uvicorn_worker.UvicornWorker -{%- else %} -web: gunicorn config.wsgi:application -{%- endif %} +web: python manage.py prodserver web {%- if cookiecutter.use_celery == "y" %} -worker: REMAP_SIGTERM=SIGQUIT celery -A config.celery_app worker --loglevel=info -beat: REMAP_SIGTERM=SIGQUIT celery -A config.celery_app beat --loglevel=info +worker: REMAP_SIGTERM=SIGQUIT python manage.py prodserver worker +beat: REMAP_SIGTERM=SIGQUIT python manage.py prodserver beat {%- endif %} diff --git a/{{cookiecutter.project_slug}}/compose/production/django/celery/beat/start b/{{cookiecutter.project_slug}}/compose/production/django/celery/beat/start index 42ddca9105..0bd085aba2 100644 --- a/{{cookiecutter.project_slug}}/compose/production/django/celery/beat/start +++ b/{{cookiecutter.project_slug}}/compose/production/django/celery/beat/start @@ -4,5 +4,5 @@ set -o errexit set -o pipefail set -o nounset - -exec celery -A config.celery_app beat -l INFO +# https://django-prodserver.readthedocs.io/en/latest/ +exec ./manage.py prodserver beat diff --git a/{{cookiecutter.project_slug}}/compose/production/django/celery/worker/start b/{{cookiecutter.project_slug}}/compose/production/django/celery/worker/start index af0c8f7b52..711974a268 100644 --- a/{{cookiecutter.project_slug}}/compose/production/django/celery/worker/start +++ b/{{cookiecutter.project_slug}}/compose/production/django/celery/worker/start @@ -4,5 +4,5 @@ set -o errexit set -o pipefail set -o nounset - -exec celery -A config.celery_app worker -l INFO +# https://django-prodserver.readthedocs.io/en/latest/ +exec ./manage.py prodserver worker diff --git a/{{cookiecutter.project_slug}}/compose/production/django/start b/{{cookiecutter.project_slug}}/compose/production/django/start index f45e7b28d4..9db27281a4 100644 --- a/{{cookiecutter.project_slug}}/compose/production/django/start +++ b/{{cookiecutter.project_slug}}/compose/production/django/start @@ -27,8 +27,5 @@ if compress_enabled; then python /app/manage.py compress fi {%- endif %} -{%- if cookiecutter.use_async == 'y' %} -exec gunicorn config.asgi --bind 0.0.0.0:5000 --chdir=/app -k uvicorn_worker.UvicornWorker -{%- else %} -exec gunicorn config.wsgi --bind 0.0.0.0:5000 --chdir=/app -{%- endif %} +# https://django-prodserver.readthedocs.io/en/latest/ +exec python /app/manage.py prodserver web diff --git a/{{cookiecutter.project_slug}}/config/settings/production.py b/{{cookiecutter.project_slug}}/config/settings/production.py index 1981be38f9..2295971663 100644 --- a/{{cookiecutter.project_slug}}/config/settings/production.py +++ b/{{cookiecutter.project_slug}}/config/settings/production.py @@ -446,5 +446,49 @@ ] {%- endif %} + +# django-prodserver +# https://django-prodserver.readthedocs.io/en/latest/ +INSTALLED_APPS += ["django_prodserver"] + +PRODUCTION_PROCESSES = { +{%- if cookiecutter.use_docker == 'y' %} + {%- if cookiecutter.use_async == 'y' %} + "web": { + "BACKEND": "django_prodserver.backends.gunicorn.GunicornServer", + "ARGS": {"bind": "0.0.0.0:5000", "chdir": "/app", "worker-class": "uvicorn_worker.UvicornWorker"}, + }, + {%- else %} + "web": { + "BACKEND": "django_prodserver.backends.gunicorn.GunicornServer", + "ARGS": {"bind": "0.0.0.0:5000", "chdir": "/app"}, + }, + {%- endif %} +{%- else %} + {%- if cookiecutter.use_async == 'y' %} + "web": { + "BACKEND": "django_prodserver.backends.gunicorn.GunicornServer", + "ARGS": {"worker-class": "uvicorn_worker.UvicornWorker"}, + }, + {%- else %} + "web": { + "BACKEND": "django_prodserver.backends.gunicorn.GunicornServer", + "ARGS": {}, + }, + {%- endif %} +{%- endif %} +{%- if cookiecutter.use_celery == 'y' %} + "worker": { + "BACKEND": "django_prodserver.backends.celery.CeleryWorker", + "APP": "config.celery_app", + "ARGS": {"loglevel": "info"}, + }, + "beat": { + "BACKEND": "django_prodserver.backends.celery.CeleryBeat", + "APP": "config.celery_app", + "ARGS": {"loglevel": "info"}, + }, +{%- endif %} +} # Your stuff... # ------------------------------------------------------------------------------ diff --git a/{{cookiecutter.project_slug}}/gulpfile.mjs b/{{cookiecutter.project_slug}}/gulpfile.mjs index 41f02b78ec..c4dad98467 100644 --- a/{{cookiecutter.project_slug}}/gulpfile.mjs +++ b/{{cookiecutter.project_slug}}/gulpfile.mjs @@ -121,7 +121,7 @@ function asyncRunServer() { {%- else %} // Run django server function runServer(cb) { - const cmd = spawn('python', ['manage.py', 'runserver'], { stdio: 'inherit' }); + const cmd = spawn('python', ['manage.py', 'devserver'], { stdio: 'inherit' }); cmd.on('close', function (code) { console.log('runServer exited with code ' + code); cb(code); diff --git a/{{cookiecutter.project_slug}}/requirements/base.txt b/{{cookiecutter.project_slug}}/requirements/base.txt index 8e37dbe2de..75d0322866 100644 --- a/{{cookiecutter.project_slug}}/requirements/base.txt +++ b/{{cookiecutter.project_slug}}/requirements/base.txt @@ -34,6 +34,7 @@ django-environ==0.12.0 # https://github.com/joke2k/django-environ django-model-utils==5.0.0 # https://github.com/jazzband/django-model-utils django-allauth[mfa]==65.13.1 # https://github.com/pennersr/django-allauth django-crispy-forms==2.5 # https://github.com/django-crispy-forms/django-crispy-forms +django-prodserver==2.3.0 # https://github.com/nanorepublica/django-prodserver crispy-bootstrap5==2025.6 # https://github.com/django-crispy-forms/crispy-bootstrap5 {%- if cookiecutter.frontend_pipeline == 'Django Compressor' %} django-compressor==4.5.1 # https://github.com/django-compressor/django-compressor