İçeriğe geç

Django Environment Variables

Giriş.

Web uygulamaları, farklı ortamlarda düzgün çalışabilmek için dışarıdan projeye aktarılan parametrelere dayanır.

Örneğin bir Django uygulaması, development, stating ve production sunucularında farklı veritabanlarına buna bağıl olarakta veritabanı iletişimini sağlayacak bilgilere ihtiyaç duyar.

Buradaki örnekler pekala çoğaltılabilir. Fakat hangi ortamda uygulama yayına alınıyorsa alınsın hassas bilgi içeren veritabanı bağlantı bilgileri, Amazon S3 konfigürasyonu yada API keyler hiç bir zaman kaynak kod içerisinde barınmamalı, versiyon takibine girmemelidir.

Kabul gören yaklaşım bu şekilde kategorilendirilebilecek hassas, yada yüksek değişim oranına sahip bilgileri environment variable olarak ayarlayıp daha sonrasında uygulamanın çalışacağı environment üstünden okumaktır. Bu yaklaşım güvenli, dağıtılabilir ve esnek bir uygulama geliştirmek için tavsiye edilir.

https://12factor.net/config üstünden detaylıca bu yaklaşıma göz atabilirsiniz.


django-environ.

django-environ, Django uygulamanızı environment variables kullanarak kolayca konfigüre etmenizi sağlayan yardımcı bir paket.

Paketin ana fikri, geliştiricinin aynı işi tekrar tekrar yapmaması ve farklı paketlerin yaptığı işlemlerin birleştirilmesi. Örneğin django-database-url.

Günün sonunda yardımcı bir paket kullanılmasa dahi geliştiricinin yaptığı işlem, OS environment üstünden okunan bir stringin, uygulama içinde kullanılabilir bir Python değişkeni haline getirilmesi.

Örneğin production environment üstünde tanımlanmış OTP_API_KEY değişkenini Django konfigürasyonunda aşağıdaki OS üstünden okuyabiliriz. Fakat kompleks değerler için manuel işlem yapmamız gerekir.

#your_project/settings.py

import os 
OTP_API_KEY = os.environ.get('OTP_API_KEY', default='useless key')

 

Paketi yükleyelim.

$ pip install django-environ

Konfigürasyon.

django-environ’ı içeriye import edip gerekli konfigürasyonu aşağıdaki gibi yapabiliriz.

#your_project/settings.py

import environ
env = environ.Env()  # initalize env instance.
environ.Env.read_env('.env')

environment variables genellikle .env ismine sahip basit plain text dosyalar üzerinde tanımlanır. ve .gitignore üzerinde ignore edilerek versiyon takibinden çıkartılır.

AWS_S3_SECRET=aws-s3-secret
AWS_S3_USER=aws-s3-user
DB_HOST=db-host.com
DB_USER=db-user
DB_PASSWORD=db-pass
SECRET_KEY=very_!secret_key!.!35!
DB_NAME=my-project-db

bu dosyayı proje dizininde oluşturalım. env üstünden artık değişken okumaya hazırız.

Environment variableların okunması.

SECRET_KEY = env('SECRET_KEY', cast=str, default="do not use in prod.")

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': env('DB_NAME', cast=str, ),
        'USER': env('DB_USER', cast=str),
        'PASSWORD': env('DB_PASSWORD', cast=str),
        'HOST': env('DB_HOST', cast=str),
        'PORT': env('DB_PORT', cast=int, default=5432),
    }
}

type casting.

cast argümanına dikkat edelim. Örneğin, Django SECRET_KEY değerini bir string, DEBUG değerini boolean, EMAIL_PORT değerini integer olarak bekler.

EMAIL_PORT = env('EMAIL_PORT', cast=int)

Esasen, cast argümanı herhangi bir callable olabilir. django-environ yerleşik Python tiplerine ve daha kompleks tiplere destek sağlar.

Birkaç farklı örneğe göz atalım;

C_LEVEL_EMAILS="john.doe@gmail.com,doe.marry@gmail.com"
DICT_EXAMPLE="key=val,foo=bar"
TRUSTED_HOSTS="example.com, localhost, 127.0.0.1"

.env dosyasına yukarıdaki değişkenleri tanımladığımızda, settings üstünde aşağıdaki gibi farklı tiplere cast edebiliriz.

#your_project/settings.py

C_LEVEL_EMAILS = env('C_LEVEL_EMAILS', cast=list)

TRUSTED_HOSTS = env('TRUSTED_HOSTS', cast=tuple)

DICT_EXAMPLE = env('DICT_EXAMPLE', cast=dict)

çıktısı aşağıdaki gibi olacaktır.

['john.doe@gmail.com', 'doe.marry@gmail.com']
('example.com', 'localhost', '127.0.0.1')
{'key': 'val', 'foo': 'bar'}

Custom caster.

env dosyası üstünden okunan stringi, list ve tuple casting sırasında django-environ varsayılan olarak “,” kullanarak ayırır. Fakat bu argümanın herhangi bir callable olabileceğinden bahsetmiştik. Dilerseniz örnekleyelim;

.env dosyası.

CUSTOM_TYPE_CAST_EXAMPLE="ceo@mail.com;cfo@mail.com;coo@mail.com"

settings.py

CUSTOM_TYPE_CAST_EXAMPLE = env(
    "CUSTOM_TYPE_CAST_EXAMPLE", cast=lambda value: value.split(";"), default=[]
)

Genellikle str, bool ve list çoğu proje için yeterli olsada, cache database gibi bağlantı şemalarını URI üstünden yönetmeniz gerekiyor olabilir.

django-environ bu URI’leri Django’nın beklediği şekildeki tipe cast ederek kullanmanıza olanak sağlayan metodlara sahiptir.

Örnek olması açısından bir postgresql bağlantı şemasını .env dosyasına ekleyelim.

DATABASE_URL=postgres://example_user:example_password@localhost:10554/example_db

sonrasında, settings.py dosyasında DATABASES‘i  aşağıdaki şekilde düzenleyebiliriz.

# your_project/settings.py

DATABASES = {
    "default" : env.db_url('DATABASE_URL')
}

django-environ sizin için aşağıdaki konfigürasyonu oluşturacaktır.

from django.conf import settings

settings.DATABASES
{'default': {'NAME': 'example_db',
  'USER': 'example_user',
  'PASSWORD': 'example_password',
  'HOST': 'localhost',
  'PORT': 10554,
  'ENGINE': 'django.db.backends.postgresql',
  'ATOMIC_REQUESTS': False,
  'AUTOCOMMIT': True,
  'CONN_MAX_AGE': 0,
  'CONN_HEALTH_CHECKS': False,
  'OPTIONS': {},
  'TIME_ZONE': None,
  'TEST': {'CHARSET': None,
   'COLLATION': None,
   'MIGRATE': True,
   'MIRROR': None,
   'NAME': None}}}

Projeyi bir bulut uygulama sağlayıcısına deploy etmek.

Projenizi bir bulut uygulama sağlayıcısına Git üstünden senkron bir şekilde deploy eden bir yapıya sahipseniz (örneğin Heroku) versiyon kontrol üstünde .env dosyası bulunduramazsınız.

Fakat bu bir problem değil. Sağlayıcının size sağladığı arayüz üstünde deployu başlatmadan önce manuel olarak değişkenlerinizi girebilirsiniz.

django-environ OS üstünde belirtilmiş değişkenleride kullanımın için içeri aktaracaktır.

Config Vars in Dashboard
Heroku environment variables dashboard.

 


İyi bir yaklaşım.

Son olarak, uygulamanızın çalışabilmesi için kritik olan değişkenlerinizi env.example adlı bir dosyada dummy değerler ile oluşturmak ve versiyon takibine dahil etmek iyi bir yaklaşımdır. Uygulamanızı gelecekte geliştirmeye devam edecek yada kurulumunu yapacak kişiye fazlasıyla yardımcı olmuş olursunuz.


Sonuç.

django-environ environment variable yönetmek için piyasadaki tek çözüm olmasa da pratikliği ile fazlaca cezbedici ve projelerde kesinlikle olması gerekli.

Öte yandan 12factor.net manifestosuna uyan uygulamalar geliştirmek uygulamanızın esnekliği, sürdürülebilirliği ve sunulabilirliğini pozitif katkıda bulunacaktır.

İyi günler!

Tarih:Featured

İlk Yorumu Siz Yapın

Bir cevap yazın

E-posta hesabınız yayımlanmayacak.

Göster
Gizle