Metadata-Version: 2.4
Name: django_run_context
Version: 1.1
Summary: Determine the context under which a Django project is run (provides a get_run_context function)
Home-page: https://github.com/bernd-wechner/django-run-context
Author: Bernd Wechner
Author-email: bwechner@yahoo.com
Project-URL: Bug Tracker, https://github.com/bernd-wechner/django-run-context/issues
Classifier: Programming Language :: Python :: 3
Classifier: License :: Freely Distributable
Classifier: Operating System :: OS Independent
Classifier: Development Status :: 5 - Production/Stable
Classifier: Framework :: Django :: 5.1
Classifier: Intended Audience :: System Administrators
Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
Requires-Python: >=3.7
Description-Content-Type: text/markdown
License-File: LICENSE.md
Requires-Dist: django>=2.2
Dynamic: license-file

# django-run-context

Determine the context under which a Django project is being run.

## Installation

```bash
pip install django-run-context
```

## Supported contexts

`get_run_context()` returns one of:

| Context | Meaning |
| --- | --- |
| `"runserver_reloader"` | The `runserver` supervising process; watches files, serves no requests |
| `"runserver_reloaded"` | The webserver process spawned by the runserver reloader |
| `"runserver_noreloader"` | `runserver` started with `--noreload` |
| `"not runserver"` | Any other context, e.g. gunicorn, uwsgi, daphne, celery, ... |

## Usage

Add it to your `settings.py`:

```python
from django_run_context import get_run_context

RUN_CONTEXT = get_run_context()
```

and access it anywhere else in the project:

```python
from django.conf import settings

print(settings.RUN_CONTEXT)
```

### Why you might need this

By default `manage.py runserver` loads `settings.py` twice: once in the
supervising process (which only watches the filesystem for changes) and again
in the reloader-spawned process that actually serves requests. Anything printed
from `settings.py` — for example diagnostics in `DEBUG` mode — therefore
appears twice.

`RUN_CONTEXT` lets you emit such output exactly once, for example:

```python
if DEBUG and RUN_CONTEXT != "runserver_reloader":
    import django
    import sys

    log.debug(f"Django version: {django.__version__}")
    log.debug(f"Python version: {sys.version}")
    log.debug(f"Django loaded from: {django.__file__}")
    log.debug(f"Using Path: {sys.path}")
    log.debug(f"Static root: {STATIC_ROOT}")
    log.debug(f"Static file dirs: {STATICFILES_DIRS}")
    log.debug(f"Installed apps: {INSTALLED_APPS}")
    log.debug(f"Database: {DATABASES['default']}")
    log.debug(f"Command line: {sys.argv}")
```

The supervising (reloader) process suppresses the output, and the real server
prints it once — whether started with the reloader (the default) or with
`--noreload`.

### Start management commands clean

Management commands (`migrate`, `shell`, custom commands, ...) all run under
`"not runserver"`. A common companion use case: dump the full diagnostics only
when a server starts up, while keeping management command startups quiet.

A typical pattern in `settings.py`:

```python
show_settings = "show_settings" in sys.argv

if DEBUG and RUN_CONTEXT not in ("runserver_reloader", "not runserver") or show_settings:
    import django
    import sys

    log.debug("SETTINGS LOADED (in context '%s'):", RUN_CONTEXT)
    log.debug("Python version: %s", sys.version)
    log.debug("Python executable: %s", sys.executable)
    log.debug("Using path: %s", sys.path)
    log.debug("Django version: %s", django.__version__)
    log.debug("Django loaded from: %s", django.__file__)
    log.debug("Installed apps: %s", INSTALLED_APPS)
    log.debug("Database: %s", DATABASES["default"])
    log.debug("Command line: %s", sys.argv)
```

Here `RUN_CONTEXT not in ("runserver_reloader", "not runserver")` means the
dump is emitted:

- in the actual runserver webserver process (`"runserver_reloaded"` /
  `"runserver_noreloader"`), not in the supervising reloader, so it appears
  only once; and
- not in management commands, so they start clean.

Passing `show_settings` as an argument to any management command forces the
dump regardless of context:

```bash
python manage.py shell show_settings
python manage.py some_command show_settings
```

## How it works

Django's autoreloader marks the spawned server process with the environment
variable `RUN_MAIN` (exposed as the private constant
`django.utils.autoreload.DJANGO_AUTORELOAD_ENV`) set to `"true"`. This module
combines that flag with the presence of `runserver` and `--noreload` in
`sys.argv` to classify the current process.

## Compatibility

- Python 3.7+
- Django 2.2+

## License

[Hippocratic License 3.0](LICENSE.md)
