Search code examples
djangodotenv

.env reload with django-environ on uwsgi


I really need some punch. I do have fully setup and running project. Django, nginx, supervisor, uwsgi - emperor with touch reload enabled.

 # {{ ansible_managed }}

[Unit]
Description=uWSGI Emperor service

[Service]
ExecStartPre=/bin/bash -c 'mkdir -p /run/uwsgi; chown {{ deploy_user }}:{{ deploy_group }} /run/uwsgi'
ExecStart=/bin/bash -c '{{ uwsgi_path }}/uwsgi --emperor /etc/uwsgi/vassals'
Restart=always
KillSignal=SIGQUIT
Type=notify
NotifyAccess=all

[Install]
WantedBy=multi-user.target

uwsgi.ini

# {{ ansible_managed }}

[uwsgi]
project = {{ project_name }}
uid = {{ deploy_user }}
gid = {{ deploy_group }}
base = /home/%(uid)

chdir = %(base)/www/{{ project_url }}/%(project)
home = %(base)/.pyenv/versions/%(project)
module = config.wsgi
;logto = /tmp/uwsgi.log

master = true
processes = 10
harakiri = 30

socket = /run/uwsgi/%(project).sock
chown-socket = %(uid):%(gid)
chmod-socket = 660
vacuum = true

touch-reload = {{ project_path }}/{{ project_name }}.touch

LANG=en_US.UTF-8
env = DJANGO_READ_DOT_ENV_FILE=True
;todo version for prod
env = DJANGO_SETTINGS_MODULE=config.settings.{{ version }}

when I make changes and touch file, it reloads everything as should, project running perfectly.

But I do have an issue with .env file.

django settings.py

import environ
...
env = environ.Env(
    # set casting, default value
    DEBUG=(bool, False)
)
# reading .env file
env.read_env(str(ROOT_DIR.path('.env')))

If I change something in .env file and upload it to the server, touch wsgi file, it does not reflect changes in .env file. If I call manuall 'service uwsgi.project restart' it loads new file content.

The question: Do I missed something in config? How can I force uwsgi to reload .env file content when touch the file.

Thank you


Solution

  • so the answer is not to use django-environ

    django-environ: ... strings from os.environ are loaded from a .env file and filled in os.environ with setdefault method, to avoid to overwrite the real environ.

    and here is the trick, if your code already set some env variable, it won't be updated on uwsgi reload, to do so, you have to restart whole service -> this is no go with zero downtime deployment nor with touch-reload.

    Using python-dotenv you are able to override this behaviour and update your envs on each reload, it works even with django dev server.

    Happy coding guys!