Django: Decouple Excerpt

Django: Decouple Excerpt

·

3 min read

In the Court of Judiciary, the loser is the one who has won, dead is the one who has lost. - Boothayyana Maga Ayyu, Kannada Cinema.

In real-world projects, sensitive and important data such as server IP address, credentials, etc, must be kept secret as much as possible.

For doing so, we have lots of tools, utilities, packages, etc. But while using such a facility, there may be problems of another kind.

Let's have an illustration.

Django Twangy:

The cookie-cutter tool is a commonly used project template starter. And provides us with a clean folder structure, .envs, for storing the data.

These data are supplied to python code via environment variables, something like:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'ecommerce-portal',
        'USER': 'postgres',
        'PASSWORD': os.environ.get('DATABASE_PASSWORD'),,
        'HOST': os.environ.get('DATABASE_HOST', default='localhost'),
        'PORT': '5432',
    }
}

Here secrets such as DATABASE_PASSWORD, DATABASE_HOST can be stored at .envs.

The Case:

In the above scenario, if Supervisor (a process control system) is used: While restarting sub-processes,

sudo supervisorctl restart ecommerce_celery

the result maybe something like:

ecommerce_celery: ERROR (not running)
ecommerce_celery: ERROR (spawn error)

If subprocess worker log is checked:

django.db.utils.OperationalError: could not connect to server: No such file or directory
        Is the server running locally and accepting
        connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?
  • supervisor runs outside the context of the virtual environment, detached from environment variables
  • In the above error case, the supervisor has not received the database name to connect.

A possible try is to pass the database name in the config file as an environment variable, like:

environment = DATABASE_HOST="255.254.253.252", .....

at /etc/supervisor/conf.d/ecommerce_celery.conf.

This does not seem to work but continues to persist with the same error.

Saviour:

python-decouple is a smart and simple solution that solves the above problem in a painless manner.

from decouple import config

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'ecommerce-portal',
        'USER': 'postgres',
        'PASSWORD': config('DATABASE_PASSWORD'),,
        'HOST': config('DATABASE_HOST', default='localhost'),
        'PORT': '5432',
    }
}

The restart does not produce the errors but runs successfully.

  1. Python Decouple
  2. Cookie Cutter
  3. Supervisor