Django Öğrenmek-4: Projeyi, “settings.py” Dosyasını Değiştirmeden Farklı Ortamlarda Çalıştırmak

Bu seride, Django öğrenirken kendi yaşadığım zorlukları ve internette okuduklarımı referans alarak Django öğrenmeye yeni başlayanlara destek olmaya çalışacağım.

Bu yazıda Django uygulamamızı farklı geliştirme ve canlı ürün ortamlarında, versiyon kontrol sistemimizden -Git, Clearcase, SVN…- çektiğimiz haline müdahale gerekmeden çalışır hale nasıl getireceğimizi konuşacağız.

Seriye ait tüm yazılara ulaşmak için:
Django Öğrenmek-1: Django öğrenmek neden zor?
Django Öğrenmek-2: Temel yapı taşları, URL, Template, Django App
Django Öğrenmek-3: Django Kurulumu, izole geliştirme ortamı “virtualenv”, Örnek Proje “Hello World”
Django Öğrenmek-4: Farklı Çalışma Ortamları İçin Farklı “settings.py” Kullanmak

Farklı Ürün Ortamları

Ürün geliştirme sırasında genellikle test ortamımızla kullanıcıların eriştiği ortamı farklı tutmayı tercih ederiz. Bu durumun, bir Django Projesi’nin settings.py dosyasına etkisi:

Ürün ortamında PostgreSQL kullanırken:

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': "remind_my_days",
'USER': "postgres",
'PASSWORD': "****",
'HOST': "localhost"
}
}

Test ortamında çok daha basit bir çözüm olan SQLite kullanmayı tercih edebilirsiniz:

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3')
}
}

Prod:

ALLOWED_HOSTS = [ 'myhost.com' ]

Test:

ALLOWED_HOSTS = [ * ]
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

Bu farklılıkları uzattıkça uzatabiliriz ama ana fikir şu:
Versiyon kontrol sistemine girdiğimiz projeyi, herhangi bir ek müdahale yapmadan direkt çekip kullanmak ya da hali hazırda çektiğimiz projeyi projenin son haline güncellemek istiyoruz.

Çözüm

Django, settings.py’ı bölmek için kendi dökümantasyonunda birkaç çözüm önerisinde bulunuyor:

Değişkenler için “ini-style” ek bir dosya kullanmak

Dosya: <my_project_home>/settings.ini

[database]
DATABASE_USER: bla
DATABASE_PASSWORD: XXXXXXXX
DATABASE_HOST: dev
DATABASE_PORT:
DATABASE_ENGINE: mysql
DATABASE_NAME: blo
TESTSUITE_DATABASE_NAME: test_blo

[secrets]
SECRET_KEY: random-string-of-ascii
CSRF_MIDDLEWARE_SECRET: random-string-of-ascii

[cookies]
SESSION_COOKIE_DOMAIN:

# all settings in debug section should be false in productive
environment
# INTERNAL_IPS should be empty in productive environment
[debug]
DEBUG: true
TEMPLATE_DEBUG: true
VIEW_TEST: true
INTERNAL_IPS: 127.0.0.1
SKIP_CSRF_MIDDLEWARE: true

<my_project_home>/settings.py

from ConfigParser import RawConfigParser

config = RawConfigParser()
config.read('<my_project_home>/settings.ini')

DATABASE_USER = config.get('database', 'DATABASE_USER')
DATABASE_PASSWORD = config.get('database', 'DATABASE_PASSWORD')
DATABASE_HOST = config.get('database', 'DATABASE_HOST')
DATABASE_PORT = config.get('database', 'DATABASE_PORT')
DATABASE_ENGINE = config.get('database', 'DATABASE_ENGINE')
DATABASE_NAME = config.get('database', 'DATABASE_NAME')
TEST_DATABASE_NAME = config.get('database', 'TESTSUITE_DATABASE_NAME')

SECRET_KEY = config.get('secrets','SECRET_KEY')
CSRF_MIDDLEWARE_SECRET = config.get('secrets', 'CSRF_MIDDLEWARE_SECRET')

SESSION_COOKIE_DOMAIN = config.get('cookies','SESSION_COOKIE_DOMAIN')

DEBUG = config.getboolean('debug','DEBUG')
TEMPLATE_DEBUG = config.getboolean('debug','TEMPLATE_DEBUG')
VIEW_TEST = config.getboolean('debug', 'VIEW_TEST')
INTERNAL_IPS = tuple(config.get('debug', 'INTERNAL_IPS').split())

Amacımıza uygun davranıp SECRET_KEY gibi özel bilgileri saklarken, değişken bilgileri de versiyon kontrol sistemimize girmemek için kontrol edilmeyecek dosya listesine -Git için .gitignore- “settings.ini” dosya adını ekliyoruz.

Birden Fazla settings Dosyası Kullanmak

Bu yöntem bir öncekinden biraz daha basit:

<my_project_home>/settings.py dosyasının içinden saklamak istediğimiz ve ortamdan ortama değişeceğini öngördüğümüz değişkenleri kaldırıyoruz veya varsayılan bir değer ile değiştiriyoruz.

<my_project_home>/settings.py

import os

BASE_DIR = os.path.dirname(os.path.abspath(__file__))

# why is this here?
#PROJECT_DIR = os.path.abspath(os.path.join(BASE_DIR, '..'))


PROJECT_DIR = BASE_DIR

DEBUG = False
TEMPLATE_DEBUG = DEBUG

DATABASE_ENGINE = 'sqlite3'
DATABASE_NAME = os.path.join(PROJECT_DIR, 'project.db')
DATABASE_USER = ''
DATABASE_PASSWORD = ''
DATABASE_HOST = ''
DATABASE_PORT = ''


TIME_ZONE = 'Europe/Zurich'
LANGUAGE_CODE = 'en-us'

SECRET_KEY = 'secret'
#[more default and app wide settings]from .settings_local import *

<my_project_home>/settings_local.py

DEBUG = True

DATABASE_ENGINE = 'mysql'
DATABASE_NAME = 'mydbname'
DATABASE_USER = 'mydbuser'
DATABASE_PASSWORD = 'mydbpassword'
DATABASE_HOST = 'localhost'
DATABASE_PORT = ''
TIME_ZONE = 'Europe/Istanbul'
LANGUAGE_CODE = 'tr-TR'
SECRET_KEY = 'random-string-of-ascii'

#[more user/machine specific settings]

settings.py dosyasının en altındaki from .settings_local import * ifadesi sayesinde “settings_local.py” dosyamızdaki değişkenler, varsayılan settings.py dosyasındaki değişkenleri eziyor. Amacımıza uygun davranıp yin değişken bilgileri versiyon kontrol sistemimize girmemek için kontrol edilmeyecek dosya listesine -Git için .gitignore- “settings_local.py” dosya adını ekliyoruz.

Django, bahsettiğimiz bu iki yöntemi ve diğer benzeri yöntemleri Django kullanıcılarının istekleri doğrultusunda toparlamış ve dökümante etmiş ama bu iş için “mükemmel” ya da varsayılan bir yöntem olmadığını da belirtmiş.

Settings’i bölmek hakkında orjinal Django dökümantasonu: https://code.djangoproject.com/wiki/SplitSettings

Serinin sonraki bölümünde, veritabanı üzerinde veri saklayıp kullanmayı öğreneceğiz. Bununla birlikte paylaşım yapabildiğimiz basit bir blog projesi olma yolunda “Simple Blog” ile kodlamaya devam edeceğiz.

Serinin, yorumlarınızdan yardım alarak gelişeceğini belirtmek istiyorum. Bu bağlamda yukarıda bahsedilen sorunları yaşadığınızı düşünüyorsanız ya da bu sorunlar dışında yaygın olarak karşılaşılan farklı sorunlar olduğunu görüyorsanız lütfen yorum bırakarak bana ve diğer kullanıcılara tavsiye ve görüşlerinizi sunmaktan çekinmeyin.

Takip etmeyi, beğenerek ve paylaşarak destek olmayı unutmayın! :)

Software Engineer, Growth & Gamification Enthusiast

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store