Использование переменных окружения для конфигурирования Django
Содержание
Крайне удобно, когда можно гибко управлять настройками своего приложения. Такими как подключение к базе данных, какие-то магические константы или ключи шифрования приложения. В Django есть механизм конфигурационных файлов, однако они не удобны тем, что они попадают в репозиторий. А это, во-первых, создаёт смешение отвественности. Репозиторий нужен для хранения исходных кодов, а не данных доступа и настроек сред. А, во-вторых, если одно и то же приложение используется в нескольких окружениях (даже дев/тест/прод) то возникает головная боль с сопровождением этих настроек и поддержкой их в актуальном состоянии. Решением этой проблемы могут стать переменные окружения.
Что такое переменные окружения
Если не вдаваться глубоко, то переменные окружения это значения, которые могут меняться в зависимости от того, где запущена программа. Хорошим примером, знакомым для всех веб-разработчиков, являются переменные окружения CGI, в которых хранятся значения домена, по которому произошёл запрос, IP адреса сервера и прочие любопытные значения. Другим примером может быть значение текущей директории в линуксе или виндовс в терминале. Которое тоже можно получить из значений переменных окружения.
Переменными окружения обычно конфигурируются параметры работы приложения в CI/CD средах, в Docker-контейнерах, в различных сессиях терминала. Удобно просто настраиваить приложение у каждого клиента через переменные окружения и в репозитории хранить только исходный код.
Примеры переменных окружения
Переменные окружения устанавливаются или через интерфейс операционной системы (системное API или через интерфейс/конфигурацию), через команды терминала или конфигурационным файлом. К примеру, просмотреть список в терминале Linux/Mac можно с помощью команды env в терминале
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
$> env LC_TERMINAL_VERSION=3.4.8 COLORFGBG=15;0 ITERM_PROFILE=Default XPC_FLAGS=0x0 SHELL=/bin/zsh TERM_PROGRAM_VERSION=3.4.8 TERM_PROGRAM=iTerm.app LC_TERMINAL=iTerm2 COLORTERM=truecolor TERM=xterm-256color XPC_SERVICE_NAME=0 SHLVL=1 PAGER=less LESS=-R LSCOLORS=Gxfxcxdxbxegedabagacad LC_ALL=ru_RU.UTF-8 LANG=ru_RU.UTF-8 LC_CTYPE=ru_RU.UTF-8 _=/usr/bin/env |
Конфигурационный файл переменных окружения по соглашению называется .env, а его пример, который можно хранить в репозитории вместе с исходными кодами .env.example .
Сам конфигурационный файл представляет собой просто строки, содержащие название переменной и её значение, разделённые знаком = . Файл может содержать комментарии, начинающиеся с символа #
К примеру, конфигурационный файл одного из djnago-проектов:
1 2 3 4 5 6 7 |
DEBUG=on SECRET_KEY='secret' DATABASE_URL=psql://urser:passd@127.0.0.1:8458/database SQLITE_URL=sqlite:///my-local-sqlite.db CACHE_URL=memcache://127.0.0.1:11211 REDIS_URL=redis://localhost:6379/ # REDIS_URL=rediscache://127.0.0.1:6379/ |
Как видно, его содержимое ничем не отличается от вывода командой env
Переменные окружения в Django
Одним из способов получить значение переменных в Django является получение значения с помощью стандартной библиотеки Python os.
Создадим представление в проекте Django (проект доступен на GitHub):
1 2 3 4 5 6 7 8 9 10 11 |
from django.shortcuts import render import os def index(request): return render( request, 'index.html', context={'variables': os.environ} ) |
И шаблон для него с выводом переменных окружения
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<!DOCTYPE html> <html lang="en"> <head> {% block title %}<title>Django environments example</title>{% endblock %} </head> <body> {% for key, value in variables.items %} <div> {{key}} => {{value}} </div> {% endfor %} </body> </html> |
В итоге, мы получили список переменных внутри докер-контейнера, в котором запущен проект:
Работа с django-environ
Чтобы воспользоваться более удобным способом, который позволяет использовать .env файлы нужно подключить библиотеку django-environ. Пользоваться этой библиотекой удобнее, потому что она поддерживает в том числе специальный синтаксис для установки параметров, специфичных для Django.
Для начала работы установим библиотеку:
1 |
pip install django-environ |
Далее, необходимо прочитать файлы переменных окружения в том месте где мы будем их использовать. Самое очевидное место для этого — файл settings.py. Добавим код:
1 2 3 4 5 6 |
env = environ.Env( # set casting, default value DEBUG=(bool, False) ) # reading .env file environ.Env.read_env() |
В нашем примере я это сделаю в файле представлений:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
from django.shortcuts import render import os import environ env = environ.Env( # set casting, default value DEBUG=(bool, False) ) # reading .env file environ.Env.read_env() # Create your views here. def index(request): return render( request, 'index.html', context={'variables': os.environ} ) def environ(request): variable_env = env('HELLO') return render( request, 'environ.html', context={'variable': variable_env} ) |
И создадим конфигурационный файл .env с содержимым
1 |
HELLO=world |
Таким образом, мы считаем переменную, которой ещё не было в нашем окружении из конфигурационного файла .env в директории с приложением environs
Вуаля, мы получили то что ожидали. Это приятно )
Более подробно о фичах библиотеки можно прочитать на официальном сайте библиотеки django-environ