İçeriğe geç

Django Çoklu Settings Modülü ile Çalışmak

Giriş.

Herkese merhabalar. settings dosyası Django projenizin kurulum ve yayın sürecinde kullanacağı tüm ayarları barındırmak ile yükümlüdür. Bu ayarlar hangi hosttan yayın yapılacağı, hangi email backendin kullanılacağı veya adminlerin email adresleri gibi bilgiler olabilir.

Ufak çaplı projelerde tek bir settings dosyası, kompleks bir yapı oluşturmadan direkt kullanıma uygundur. Fakat projeniz büyüdükçe bu yaklaşım bir takım kısıtlamalar doğurur.

  • Environment yönetimi. Geliştirme ortamı, test ortamı, canlı ortamı veya deploy öncesi çalıştırılan ci toollarının ihtiyaç duyduğu konfigürasyonlarının da projenin ayakta kalması adına tanımlanma gerekliliği fakat ayrık olamaması.
  • Bağımlılıkların her ortam için kontrol edilmesi, değiştirilmesi. (settings dosyası üzerinde büyüyen if else blokları)
  • Hassas olabilecek verilerin, örneğin 3rd party API keylerin veya tokenların versiyon kontrol sistemi dışında tutularak güvenliğin sağlanması.
  • Birden fazla geliştiricinin çalıştığı ortamlarda kalıp bir settings yapısının oluşturulamaması, projenin geliştirme sürecinin yavaşlaması vs.

 


Proje şeması.

 

tree -I '*pyc*|venv' 
.
├── db.sqlite3
├── example_project
│   ├── asgi.py
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── manage.py

Basit bir Django projei şema olarak yukarıdaki gibidir. Bu yapıyı geliştirerek, farklı ortamlarda kullanılmak üzere settings dosyaları oluşturacak yukarıdaki kısıtlamalara çözüm üreteceğiz.

İlk olarak proje dizininde bir adet settings modülü oluşturalım. Bu modüle ilk olarak tüm ortamlarda ortak kullanılan konfigürasyonları barındıracak base.py ‘i daha sonrasında lokal(geliştirme), stage ve canlı ortamlarda kullanılmak üzere diğer settings dosyalarını tanımlayacağız.

base.py dosyası içine proje genelinde ortak kullanılacak olan ayarlamaları ( Örneğin INSTALLED_APPS veya MIDDLEWARE) veya tamamını daha sonra genişletmek üzere kopyalayalım.

from pathlib import Path

BASE_DIR = Path(__file__).resolve().parent.parent

SECRET_KEY = '=hs2+2vvtp(bx$-%cmkw(ek#th(oo++##0ni24#v&=^hpdk4ln'

DEBUG = True

ALLOWED_HOSTS = []

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
# other settigns

stage, dev, ve prod dosyalarını da oluşturalım. Yeni şema aşağıdaki gibi olmalıdır.

$ tree -I '*pyc*|venv'
.
├── db.sqlite3
├── example_project
│   ├── asgi.py
│   ├── __init__.py
│   ├── settings
│   │   ├── base.py
│   │   ├── dev.py
│   │   ├── __init__.py
│   │   ├── prod.py
│   │   └── stage.py
│   ├── urls.py
│   └── wsgi.py
└── manage.py

Farklı ortamların ihtiyaçlarına göre settings dosyalarını genişletelim.

Örneğin geliştirme ortamı;

#settings/dev.py

from .base import *

DEBUG = True

ALLOWED_HOSTS = ["localhost","127.0.0.1"]

INSTALLED_APPS.extend(["debug_toolbar", "django_extensions"])

MIDDLEWARE.extend(
    [
        "debug_toolbar.middleware.DebugToolbarMiddleware",
        "other.middleware.you.use.to.for.debug",
    ]
)

EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"

CELERY_ALWAYS_EAGER = True

BROKER_URL = "redis://127.0.0.1:6379/1"

GATEWAYS = {
    "example": {
        "api_key": "test-key",
        "url": "test.gateway.com",
        "klass": "test.gateway.for.use.dev",
    },
}

Örnek olması açısından doğrudan envden okunan ve hardcoded olmayan prod settingsi.

#settings/prod.py
from .base import *
import os

DEBUG = False

ALLOWED_HOSTS = ["your-app.com"]
SECRET_KEY = os.environ.get("SECRET_KEY")

MIDDLEWARE.extend(
    [
        "your.data.analysis.middleware",
        "django.middleware.locale.LocaleMiddleware",
    ]
)

EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"
EMAIL_HOST = "smtp.gmail.com"
EMAIL_PORT = 587
EMAIL_HOST_USER = os.environ.get("EMAIL_HOST_USER")
EMAIL_HOST_PASSWORD = os.environ.get("EMAIL_HOST_PASSWORD")
EMAIL_USE_TLS = True


BROKER_URL = os.environ.get("CELERY_BROKER_URL")

GATEWAYS = {
    "example": {
        "api_key": os.environ.get("EXAMPLE_GATEWAY_API_KEY"),
        "url": os.environ.get("EXAMPLE_GATEWAY_URL"),
        "klass": "prod.gateway.for.use.dev",
    },
}

Ayrık settingsleri kullanma ve DJANGO_SETTINGS_MODULE.

Django komutları çalıştırılır iken (runserver, migrate veya makemigrations vs) üzerinde çalıştığı sistemdeki DJANGO_SETTINGS_MODULE değişkenini arar. Bu değişken o ortamda tanımlı değil ise varsayılan proje şemasındaki settings modülü dikkate alınır ve komut koşturulmaya çalışılır.

Fakat artık ayrık settings dosyalarına sahip olduğumuzdan ya bu değeri çalışılan ortama setlemeli ya da komutun çalışma esnasında parametre olarak geçmeliyiz.

$ python manage.py runserver --settings=example_project.settings.dev
$ python manage.py migrate --settings=example_project.settings.prod

Uzun lafın kısası 🙂

Her seferinde doğru settings dosyasını açıkca belirtmek istemiyor iseniz aşağıdaki gibi çalışılan ortama setleyedebilirsiniz. Fakat verdiğiniz yolu 2 defa kontrol etmekte fayda var bir bakmışssınız ki debug modda canlıya çıkmışsınız 😀

$ export DJANGO_SETTINGS_MODULE=example_project.settings.dev

Sonuç.

settings dosyaları Django projeniz için küçük ama önemli bir kısım. İyi bir yapı kurgulanır ise, projeniz ne kadar büyürse büyüsün esnek ve yönetebilir bir konfigürasyon elde edersiniz. Bunun yanında, açıkça yazılmasa da, Django’nun varsayılan bir çok settings değeri bulunmakta. Bu değerler hakkında da alakalı bilgi almak isterseniz link burada.

Django ile alakalı daha fazla okumak isterseniz.

İyi günler dilerim!

Tarih:Blog

İlk Yorumu Siz Yapın

Bir cevap yazın

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

Göster
Gizle