Django'da yerel vs üretim ayarları nasıl yönetilir?


298

Yerel geliştirme ve üretim sunucusu için ayarların ele alınması için önerilen yol nedir? Bazılarının (sabitler vb. Gibi) her ikisinde de değiştirilebilir / erişilebilir, ancak bazılarının (statik dosyalara giden yollar gibi) farklı kalması gerekir ve bu nedenle yeni kod her konuşlandırıldığında üzerine yazılmamalıdır.

Şu an için tüm sabitleri ekliyorum settings.py. Ancak her sabit yerel olarak değiştirdiğimde, bunu üretim sunucusuna kopyalamam ve dosyayı üretime özgü değişiklikler için düzenlemem gerekiyor ... :(

Düzenleme: Bu soruya standart bir cevap yok gibi görünüyor, en popüler yöntemi kabul ettim.



Lütfen django yapılandırmalarına bir göz atın .
JJD

2
Kabul edilen yöntem artık en popüler yöntem değildir.
Daniel

2
django-split-ayarlarının kullanımı çok kolaydır. Herhangi bir varsayılan ayarın yeniden yazılmasını gerektirmez.
sobolevn

base.py dosyasını kullanmalısınız ve local.py dosyasında ".base içe aktarma *" dan aynı, production.py ".base içe aktarma *" dan aynı şekilde projenizi çalıştırmalısınız: python manage.py runserver - settings = project_name.settings.local
Roberth Solís

Yanıtlar:


127

İçinde settings.py:

try:
    from local_settings import *
except ImportError as e:
    pass

İhtiyacınız olanı geçersiz kılabilirsiniz local_settings.py; o zaman sürüm kontrolünüzün dışında kalmalıdır. Ama kopyalamadan bahsettiğiniz için hiçbirini kullanmamanızı tahmin ediyorum;)


3
Yeni ayarların izlenmesini / dağıtılmasını kolaylaştırmak için üretim / test makinelerinde "local_settings.py" kullanın ve geliştirme sırasında hiçbiri kullanmayın.
John Mee

8
Bu şekilde yapıyorum - bu satırları settings.py'nin sonuna ekleyerek varsayılan ayarları geçersiz kılabilirler
daonb

61
Bu yaklaşım, geliştirme ve üretimde çalışan kodun sürümünüzün olmadığı anlamına gelir. Ve her geliştiricinin farklı bir kod tabanı var.Burada anti-desen çağırıyorum.
pydanny

8
@pydanny Sorun, Django'nun yapılandırmasını .py dosyasında depolamasıdır. Tüm geliştiricilerin ve üretim sunucusunun aynı ayarları kullanmasını bekleyemezsiniz, bu nedenle bu .py dosyasını değiştirmeniz veya alternatif bir çözüm (.ini dosyaları, ortam vb.) Uygulamanız gerekir.
Tupteq

3
Alfabetik klasör listelerinde gruplamak settings_localyerine modülü çağırmayı tercih ederim . Kimlik bilgileri Git'e ait olmadığından , sürüm denetiminin dışında tutun . Kazara onları açık kaynak hayal edin. Git adı verilen bir şablon dosyasını git . local_settingssettings.pysettings_local.py.gitignoresettings_local.py.txt
fmalina

297

Django'nun İki Kepçe: Django 1.5 için En İyi Uygulamalar , ayar dosyalarınız için sürüm kontrolünü kullanmanızı ve dosyaları ayrı bir dizinde depolamanızı önerir:

project/
    app1/
    app2/
    project/
        __init__.py
        settings/
            __init__.py
            base.py
            local.py
            production.py
    manage.py

base.pyİse dosya (örneğin MEDIA_ROOT veya ADMIN gibi) ortak ayarları içerir local.pyve production.pybölgeye özel ayarları vardır:

Temel dosyada settings/base.py:

INSTALLED_APPS = (
    # common apps...
)

Yerel geliştirme ayarları dosyasında settings/local.py:

from project.settings.base import *

DEBUG = True
INSTALLED_APPS += (
    'debug_toolbar', # and other apps for local development
)

Dosya üretim ayarları dosyasında settings/production.py:

from project.settings.base import *

DEBUG = False
INSTALLED_APPS += (
    # other apps for production site
)

Sonra django çalıştırdığınızda, --settings seçeneği :

# Running django for local development
$ ./manage.py runserver 0:8000 --settings=project.settings.local

# Running django shell on the production site
$ ./manage.py shell --settings=project.settings.production

Kitabın yazarları da Github'da örnek bir proje düzeni şablonu hazırladılar.


62
--settingsHer seferinde kullanmak yerine , DJANGO_SETTINGS_MODULEenvvar'ı ayarlayabileceğinizi unutmayın. Bu, örneğin Heroku ile iyi çalışır: global olarak üretime ayarlayın, ardından .env dosyanızdaki dev ile geçersiz kılın.
Simon Weber

9
DJANGO_SETTINGS_MODULEEnv var kullanmak burada en iyi fikir, teşekkürler Simon.
kibibu

20
BASE_DIRAyarları değiştirmeniz gerekebiliros.path.dirname(os.path.realpath(os.path.dirname(__file__) + "/.."))
Petr Peller

5
@rsp, django belgelerine göre, içe aktarılan from django.conf import settingsve arayüzü ayarların konumundan kodu çözen

3
DJANGO_SETTINGS_MODULE cihazını çevresel bir değişken aracılığıyla ayarlarsam, wsgi.py dosyamda hala os.environ.setdefault ("DJANGO_SETTINGS_MODULE", "projectname.settings.production") gerekir mi? Ayrıca, çevre değişkenini kullanarak ayarladım: export DJANGO_SETTINGS_MODULE = projectname.settings.local, ancak terminali kapattığımda kayboluyor. Kaydedilmesini sağlamak için ne yapabilirim? Bu satırı bashrc dosyasına eklemeli miyim?
Kritz

71

Bunun yerine settings.pyşu düzeni kullanın:

.
└── settings/
    ├── __init__.py  <= not versioned
    ├── common.py
    ├── dev.py
    └── prod.py

common.py yapılandırmanızın çoğunun yaşadığı yerdir.

prod.py her şeyi ortak olandan içe aktarır ve geçersiz kılmak için gerekenleri geçersiz kılar:

from __future__ import absolute_import # optional, but I like it
from .common import *

# Production overrides
DEBUG = False
#...

Benzer şekilde, dev.pyher şeyi içe aktarır common.pyve geçersiz kılmak için ne gerekiyorsa geçersiz kılar.

Son olarak, __init__.pyhangi ayarların yükleneceğine karar verdiğiniz yerdir ve aynı zamanda sırları sakladığınız yerdir (bu nedenle bu dosya sürümlendirilmemelidir):

from __future__ import absolute_import
from .prod import *  # or .dev if you want dev

##### DJANGO SECRETS
SECRET_KEY = '(3gd6shenud@&57...'
DATABASES['default']['PASSWORD'] = 'f9kGH...'

##### OTHER SECRETS
AWS_SECRET_ACCESS_KEY = "h50fH..."

Bu çözüm hakkında ne gibi:

  1. Sırlar hariç her şey sürüm sisteminizde
  2. Çoğu konfigürasyon tek bir yerde geçerli: common.py.
  3. Prod özgü işlerin prod.py, dev özgü şeyler gitmek dev.py. Basit.
  4. Sen bir şeyler geçersiz kılabilir common.pyiçinde prod.pyya dev.pyve de her şeyden önemli olabilir__init__.py .
  5. Bu basit bir piton. Yeniden içe aktarma kesmek yok.

2
Hala ayarları dosya için benim project.wsgi ve manage.py dosyaları ayarlamak için ne anlamaya çalışıyorum. Buna biraz ışık tutacak mısın? Özellikle, benim manage.py dosyamda os.environ.setdefault("DJANGO_SETTINGS_MODULE", "foobar.settings")foobar bir __init__.pydosya ile bir klasör var ve ayarları __init__.pybenim sırları içeren ve daha sonra common.py ithal dev.py ithal bir dosya ile bir klasör var . EDIT Nevermind, gerekli bir modülüm yoktu. Benim hatam! Bu harika çalışıyor !!
teewuane

5
İki şey: 1) prod.py'nizde = Yanlış yerine hata ayıklama = dev.py'de True değerini ayarlamak daha iyidir. 2) init .py'ye geçmek yerine DJANGO_SETTINGS_MODULE ortam var. Bu, PAAS dağıtımlarında (ör. Heroku) yardımcı olacaktır.
Rob Grant

Bu kurulumu django 1.8.4'te kullandığımda ve runserver'ı denediğimde "django.core.exceptions.ImproperlyConfigured: SECRET_KEY ayarı boş olmamalıdır.", Hatta doh benim init .py dosyamda SECRET_KEY var . Bir şey mi kaçırıyorum?
polarcare

AWS_SECRET_ACCESS_KEY = os.getenv ("AWS_SECRET_ACCESS_KEY") gibi bir şeyin kullanımı daha güvenli değil mi? Dürüst soru - Neden sürümlendirilmesini istemediğinizi biliyorum, ancak diğer alternatif bunu ortamdan elde etmektir. Hangi ortam değişkenini ayarlama sorusu elbette, ama bu dağıtım mekanizmanıza bırakılabilir, hayır?
JL Peyret

20

Harper Shelby tarafından yayınlanan "if DEBUG" ayarlarının biraz değiştirilmiş bir versiyonunu kullanıyorum. Açıkçası ortama bağlı olarak (win / linux / etc.) Kodun biraz değiştirilmesi gerekebilir.

Geçmişte "if DEBUG" kullanıyordum ama ara sıra DEUBG ile False olarak ayarlanmış bir test yapmam gerektiğini fark ettim. Ortamın üretim veya geliştirme olup olmadığını gerçekten ayırt etmek istediğim şey, bana DEBUG seviyesini seçme özgürlüğü verdi.

PRODUCTION_SERVERS = ['WEBSERVER1','WEBSERVER2',]
if os.environ['COMPUTERNAME'] in PRODUCTION_SERVERS:
    PRODUCTION = True
else:
    PRODUCTION = False

DEBUG = not PRODUCTION
TEMPLATE_DEBUG = DEBUG

# ...

if PRODUCTION:
    DATABASE_HOST = '192.168.1.1'
else:
    DATABASE_HOST = 'localhost'

Hala bu tür ayarları devam eden bir çalışma olarak görüyorum. Tüm üsleri kapsayan Django ayarlarını işlemek için herhangi bir yol görmedim ve aynı zamanda kurulum için toplam güçlük değildi (5x ayarları dosyaları yöntemleri ile aşağı değilim).


Bu, Django'nun ayarlarının gerçek bir kod dosyası olmasına izin veren bir şey ve ben de ima ediyordum. Ben böyle bir şey yapmadım, ama kesinlikle benimkinden daha iyi bir genel cevap olabilecek bir çözüm.
Harper Shelby

3
Ben sadece ilk kez bu çalıştım ve küçük bir farkla, çözümünüzü (başarıyla!) Kullanmayı seçtim: Sistemimin uuid bulmak için uuid.getnode () kullandım. Kullandığınız os.environ testi yerine uuid.getnode () == 12345678901 (aslında farklı bir sayı) olup olmadığını test ediyorum. Beni os.environ ['COMPUTERNAME'] bilgisayar başına benzersiz olduğuna ikna edecek belgeler bulamadım.
Joe Golton

os.environ ['BİLGİSAYARADI'] Amazon AWS Ubuntu üzerinde çalışmaz. Bir KeyError alıyorum.
nu everest

UUID kullanırken bu çözümün benim için en iyi ve en basit olduğu kanıtlanmıştır. Çok fazla karmaşık ve aşırı modülerleştirilmiş patchwork gerektirmez. Üretim ortamında, veritabanı şifrelerinizi ve SECRET_KEY'i sürüm kontrolü dışında bulunan ayrı bir dosyaya koymanız gerekir.
nu everest

os.environ['COMPUTERNAME']ne yazık ki PythonAnywhere üzerinde çalışmıyor. Bir KeyError alıyorsunuz.
nbeuchat

14

Bir settings_local.py ve bir settings_production.py kullanıyorum. Birkaç seçeneği denedikten sonra, iki ayar dosyasına sahip olmak kolay ve hızlı olduğunda karmaşık çözümlerle zaman kaybetmenin kolay olduğunu gördüm.

Django projeniz için mod_python / mod_wsgi kullandığınızda, onu ayarlar dosyanıza yönlendirmeniz gerekir. Yerel sunucunuzda app / settings_local.py ve üretim sunucunuzda app / settings_production.py üzerine yönlendirirseniz, yaşam kolaylaşır. Uygun ayarlar dosyasını düzenleyin ve sunucuyu yeniden başlatın (Django geliştirme sunucusu otomatik olarak yeniden başlatılır).


2
Peki ya yerel geliştirme sunucusu? django web sunucusuna (kullanarak çalıştırın python manage.py runserver), hangi ayarlar dosyasını kullanacağını söylemenin bir yolu var mı?
akv

2
@akv runserver komutunun sonuna --settings = [modül adı] (.py uzantısı yok) eklerseniz hangi ayar dosyasını kullanacağınızı belirleyebilirsiniz. Bunu yapacaksanız, kendinize bir iyilik yapın ve yapılandırılmış geliştirme ayarları ile bir kabuk komut dosyası / toplu iş dosyası oluşturun. Güven bana, parmakların sana teşekkür edecek.
T. Stone

kullandığım çözüm bu. hem üretim hem de geliştirme için kullanılacak bir ayarlar dosyasını hacklemek dağınık
George Godik

4
Her zaman belirtmeniz gerekmediğinden, settings.py'yi geliştirme aşamasında kullanmak daha iyi olduğunu düşünüyorum.
Andre Bossard

Bu yöntemin django.conf.settings proxy'si üzerinden ayarlar modülünün içe aktarılmasını gerektirdiğini varsayarak doğru muyum? Aksi takdirde, canlı yayın aktarırken doğru ayarlar dosyasını gösterecek şekilde içe aktarma bildirimlerini düzenlemeniz gerekir.
Groady

8

TL; DR: hile değiştirmektir os.environmentİçe aktarmadan önce settings/base.pyherhangi settings/<purpose>.py, bu işleri bir hayli kolaylaştıracak.


Tüm bu iç içe geçmiş dosyaları düşünmek başım ağrıyor. DEBUGDaha sonra değiştiğinde ayarlanmış olanları birleştirme, içe aktarma (bazen koşullu olarak), geçersiz kılma, yama . Ne kabustu ama!

Yıllar boyunca tüm farklı çözümlerden geçtim. Hepsi biraz işe yarıyor, ama yönetmek çok acı verici. O NE LAN! Tüm bu güçlüklere gerçekten ihtiyacımız var mı? Sadece bir settings.pydosya ile başladık . Şimdi tüm bunları doğru bir şekilde doğru bir şekilde bir araya getirmek için bir dokümana ihtiyacımız var!

Umarım sonunda (benim) tatlı noktaya aşağıdaki çözümle vurdum.

Hedefleri özetleyelim (bazıları ortak, bazıları benim)

  1. Sırları bir sır olarak saklayın - onları bir depoda saklamayın!

  2. Ortam ayarları, 12 faktör stili ile anahtarları ve sırları ayarlayın / okuyun .

  3. Mantıklı yedek varsayılanlara sahip olun. İdeal olarak yerel kalkınma için varsayılanların yanında başka bir şeye ihtiyacınız yoktur.

  4. … Ama varsayılan üretimi güvende tutmaya çalışın. Varsayılan ayarları üretim için güvenli olarak ayarlamayı hatırlamak zorunda kalmaktan ziyade, yerel olarak bir ayar geçersiz kılmayı kaçırmak daha iyidir.

  5. DEBUGDiğer ayarlar üzerinde etkili olabilecek bir şekilde açma / kapama yeteneğine sahip olma (örn. Javascript'i sıkıştırılmış veya kullanmama).

  6. Yerel / test / aşamalandırma / üretim gibi amaç ayarları arasında geçiş yapmak, yalnızca DJANGO_SETTINGS_MODULEbaşka bir şeye dayanmamalıdır .

  7. … Ancak gibi ortam ayarları ile daha fazla parametrelendirmeye izin verin DATABASE_URL.

  8. … Ayrıca farklı amaç ayarları kullanmalarına ve bunları yan yana yerel olarak çalıştırmalarına izin verin, örn. üretim veritabanına veya duman testi sıkıştırılmış stil sayfalarına erişmek için yerel geliştirici makinesinde üretim kurulumu.

  9. Bir ortam değişkeni, özellikle üretimde, örneğin, açık bir şekilde ayarlanmamışsa (minimumda boş bir değer gerektirir) başarısız olur. EMAIL_HOST_PASSWORD.

  10. Django-admin startprojectDJANGO_SETTINGS_MODULE sırasında manage.py içinde ayarlanan varsayılana yanıt verin

  11. Koşul ise, minimumda conditionals tutun amaçlı çevre tipi (örn. Üretim seti günlük dosyası ve 's dönüş için), ilişkili amaçlı ayarlar dosyasındaki ayarları geçersiz kılar.

Yapma

  1. Django'nun bir dosyadan DJANGO_SETTINGS_MODULE ayarını okumasına izin vermeyin.
    Ihh! Bunun ne kadar meta olduğunu düşünün. Bir dosyaya (docker env gibi) ihtiyacınız varsa, bir django işlemine başlamadan önce bu ortamı okuyunuz.

  2. Proje / uygulama kodunuzdaki DJANGO_SETTINGS_MODULE'u geçersiz kılınmayın, örn. ana bilgisayar adı veya işlem adına göre.
    Ortam değişkenini (gibi setup.py test) ayarlamak için tembelseniz, proje kodunuzu çalıştırmadan hemen önce takım içinde bunu yapın.

  3. Django'nun ayarlarını nasıl okuduğuna dair sihir ve yamalardan kaçının, ayarları önceden işleyin, ancak daha sonra müdahale etmeyin.

  4. Karmaşık mantık tabanlı saçmalık yok. Konfigürasyon sabitlenmeli ve anında hesaplanmadan gerçekleştirilmelidir. Burada geri dönüş varsayılanları sağlamak yeterli bir mantıktır.
    Gerçekten hata ayıklamak istiyor musunuz, neden yerel olarak doğru ayar kümeniz var, ancak uzak bir sunucuda, yüz makineden birinde, farklı bir şekilde hesaplanan bir şey üretiliyor? Ah! Birim testleri? Ayarlar için? Ciddi anlamda?

Çözüm

Stratejim, stil dosyaları ile kullanılan , yerel geliştirme için varsayılanlar sağlayan bir dosyadan ayarlandıktan SONRA en az ve kısa dosyaları içeren mükemmel django-environ'dan oluşur . Bu bize etkili bir şekilde ayar enjeksiyonunu verir.inios.environmentsettings/<purpose>.pyimport settings/base.py os.environmentINI

Buradaki hile, os.environmentiçe aktarmadan önce değişiklik yapmaktır settings/base.py.

Tam örneği görmek için şu repoya gidin: https://github.com/wooyek/django-settings-strategy

.
   manage.py
├───data
└───website
    ├───settings
          __init__.py   <-- imports local for compatibility
          base.py       <-- almost all the settings, reads from proces environment 
          local.py      <-- a few modifications for local development
          production.py <-- ideally is empty and everything is in base 
          testing.py    <-- mimics production with a reasonable exeptions
          .env          <-- for local use, not kept in repo
       __init__.py
       urls.py
       wsgi.py

ayarlar / .env

Yerel kalkınma için varsayılanlar. Çoğunlukla gerekli ortam değişkenlerini ayarlamak için gizli bir dosya. Yerel geliştirme için gerekli değilse, bunları boş değerlere ayarlayın. Burada varsayılanları sağlarız ve settings/base.pyortamdan eksikse başka herhangi bir makinede başarısız olmaz .

ayarlar / local.py

Burada olan, ortamın yüklenip settings/.envardından ortak ayarların içe aktarılmasıdır settings/base.py. Bundan sonra yerel kalkınmayı kolaylaştırmak için birkaçını geçersiz kılabiliriz.

import logging
import environ

logging.debug("Settings loading: %s" % __file__)

# This will read missing environment variables from a file
# We wan to do this before loading a base settings as they may depend on environment
environ.Env.read_env(DEBUG='True')

from .base import *

ALLOWED_HOSTS += [
    '127.0.0.1',
    'localhost',
    '.example.com',
    'vagrant',
    ]

# https://docs.djangoproject.com/en/1.6/topics/email/#console-backend
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
# EMAIL_BACKEND = 'django.core.mail.backends.dummy.EmailBackend'

LOGGING['handlers']['mail_admins']['email_backend'] = 'django.core.mail.backends.dummy.EmailBackend'

# Sync task testing
# http://docs.celeryproject.org/en/2.5/configuration.html?highlight=celery_always_eager#celery-always-eager

CELERY_ALWAYS_EAGER = True
CELERY_EAGER_PROPAGATES_EXCEPTIONS = True

ayarlar / production.py

Üretim için bir ortam dosyası beklememeliyiz, ancak bir şeyi test edersek bir dosyaya sahip olmak daha kolaydır. Ama neyse, satır içi birkaç varsayılan sağlamak, bu yüzden settings/base.pybuna göre cevap verebilir.

environ.Env.read_env(Path(__file__) / "production.env", DEBUG='False', ASSETS_DEBUG='False')
from .base import *

Buradaki temel ilgi alanı DEBUGve ASSETS_DEBUGgeçersiz kılmalar, os.environSADECE ortamdan ve dosyadan EKSİKSİZLER ise python'a uygulanacaktır .

Bunlar üretim varsayılanlarımız olacak, onları ortama veya dosyaya koymaya gerek yok, ancak gerekirse geçersiz kılınabilir. Temiz!

ayarları / base.py

Bunlar çoğunlukla vanilya django ayarlarınızdır, birkaç koşul ve onları ortamdan okumaları çoktur. Neredeyse her şey burada, amaçlanan tüm ortamları tutarlı ve mümkün olduğunca benzer tutar.

Temel farklılıklar aşağıdadır (umarım bunlar açıklayıcıdır):

import environ

# https://github.com/joke2k/django-environ
env = environ.Env()

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

# Where BASE_DIR is a django source root, ROOT_DIR is a whole project root
# It may differ BASE_DIR for eg. when your django project code is in `src` folder
# This may help to separate python modules and *django apps* from other stuff
# like documentation, fixtures, docker settings
ROOT_DIR = BASE_DIR

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = env('SECRET_KEY')

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = env('DEBUG', default=False)

INTERNAL_IPS = [
    '127.0.0.1',
]

ALLOWED_HOSTS = []

if 'ALLOWED_HOSTS' in os.environ:
    hosts = os.environ['ALLOWED_HOSTS'].split(" ")
    BASE_URL = "https://" + hosts[0]
    for host in hosts:
        host = host.strip()
        if host:
            ALLOWED_HOSTS.append(host)

SECURE_SSL_REDIRECT = env.bool('SECURE_SSL_REDIRECT', default=False)

# Database
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases

if "DATABASE_URL" in os.environ:  # pragma: no cover
    # Enable database config through environment
    DATABASES = {
        # Raises ImproperlyConfigured exception if DATABASE_URL not in os.environ
        'default': env.db(),
    }

    # Make sure we use have all settings we need
    # DATABASES['default']['ENGINE'] = 'django.contrib.gis.db.backends.postgis'
    DATABASES['default']['TEST'] = {'NAME': os.environ.get("DATABASE_TEST_NAME", None)}
    DATABASES['default']['OPTIONS'] = {
        'options': '-c search_path=gis,public,pg_catalog',
        'sslmode': 'require',
    }
else:
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.sqlite3',
            # 'ENGINE': 'django.contrib.gis.db.backends.spatialite',
            'NAME': os.path.join(ROOT_DIR, 'data', 'db.dev.sqlite3'),
            'TEST': {
                'NAME': os.path.join(ROOT_DIR, 'data', 'db.test.sqlite3'),
            }
        }
    }

STATIC_ROOT = os.path.join(ROOT_DIR, 'static')

# django-assets
# http://django-assets.readthedocs.org/en/latest/settings.html

ASSETS_LOAD_PATH = STATIC_ROOT
ASSETS_ROOT = os.path.join(ROOT_DIR, 'assets', "compressed")
ASSETS_DEBUG = env('ASSETS_DEBUG', default=DEBUG)  # Disable when testing compressed file in DEBUG mode
if ASSETS_DEBUG:
    ASSETS_URL = STATIC_URL
    ASSETS_MANIFEST = "json:{}".format(os.path.join(ASSETS_ROOT, "manifest.json"))
else:
    ASSETS_URL = STATIC_URL + "assets/compressed/"
    ASSETS_MANIFEST = "json:{}".format(os.path.join(STATIC_ROOT, 'assets', "compressed", "manifest.json"))
ASSETS_AUTO_BUILD = ASSETS_DEBUG
ASSETS_MODULES = ('website.assets',)

Son bit, burada gücü gösterir. ASSETS_DEBUGmantıklı bir varsayılana sahiptir, bu settings/production.pyayar geçersiz kılınabilir ve hatta bir ortam ayarı tarafından geçersiz kılınabilir! Yaşasın!

Aslında karışık bir hiyerarşimiz var:

  1. settings / .py - amaca göre varsayılanları ayarlar, sır saklamaz
  2. settings / base.py - çoğunlukla çevre tarafından kontrol edilir
  3. işlem ortamı ayarları - 12 faktör bebek!
  4. settings / .env - kolay başlatma için yerel varsayılanlar

Hey Janusz ... yani .env dosyasında tüm API anahtarları ve yetkilendirme anahtarları ve parolalar vb. Tıpkı TWILLIO_API = "abc123" gibi mi? Veya TWILLIO_API = env ("TWILLIO_API")?
dbinott

Evet, ancak bu yalnızca ortam ayarları için bir geri dönüş. Bu dosya geliştirme için kullanışlıdır, ancak ortam ayarlarını veya sunucu eşdeğeri için ortam ayarlarını ayarlayacak platform eşdeğerini kesinlikle kullanmanız gereken repo'ya kaydedilmez veya üretime gönderilmez.
Janusz Skonieczny

7

Konfigürasyonlarımı django-split-settings yardımıyla yönetiyorum .

Varsayılan ayarlar için bir yedek yedektir. Basit, ancak yapılandırılabilir. Mevcut ayarlarınızın yeniden düzenlenmesi gerekmez.

İşte küçük bir örnek (dosya example/settings/__init__.py):

from split_settings.tools import optional, include
import os

if os.environ['DJANGO_SETTINGS_MODULE'] == 'example.settings':
    include(
        'components/default.py',
        'components/database.py',
        # This file may be missing:
        optional('local_settings.py'),

        scope=globals()
    )

Bu kadar.

Güncelleme

Ayarlarını yönetmeyle ilgili bir blog yazısı yazdım . Bir bak!djangodjango-split-sttings


1
Ben denedim .. benim django birim testleri çalıştırmak için çalıştı bir kez bir duvara koştu .. ben sadece hangi ayarları dosyasını okumak için belirtmek için nasıl anlayamadım
abbood

Senin için bir yumruk
sobolevn

i gibi bir şey var bu i şeyler içe istersen bende bilmek settings.DEBUG bayrağını kontrol böylece .. O bayrağın her zaman (bkz Django birim testlerinde false olarak ayarlanır, benim kodunda burada işim etrafında onları geçersiz kılmak için bu yüzden) gibi her test yüzden
abbood

yine de başka bir soru var: benim uwsgi.inidosya dev / prod genelinde farklı ayarları var .. benim ayarları dosyadan değerleri seçmek nasıl herhangi bir fikir?
abbood

Üzgünüm, kurulumu alamıyorum. daha fazla ayrıntı ile ayrı bir soru sorabilirsiniz ve ben size yardımcı olmaya çalışacağım.
sobolevn

6

Bu çözümlerin çoğundaki sorun, ya yerel ayarlarınızın uygulanmış olmasıdır. yaygın olanlardan önce veya onlardan sonra .

Yani, şu gibi şeyleri geçersiz kılmak imkansız

  • env'ye özgü ayarlar memcached havuzunun adreslerini tanımlar ve ana ayarlar dosyasında bu değer önbellek arka ucunu yapılandırmak için kullanılır
  • env'ye özgü ayarlar, varsayılana uygulamalar / ara katman yazılımı ekler veya kaldırır

aynı zamanda.

Bir çözüm, ConfigParser sınıfına sahip "ini" tarzı yapılandırma dosyaları kullanılarak uygulanabilir. Birden fazla dosya, tembel dize enterpolasyonu, varsayılan değerler ve diğer birçok özelliği destekler. Bir dizi dosya yüklendikten sonra, daha fazla dosya yüklenebilir ve değerleri varsa öncekilerin üzerine yazılır.

Makine adresine, ortam değişkenlerine ve hatta önceden yüklenmiş yapılandırma dosyalarındaki değerlere bağlı olarak bir veya daha fazla yapılandırma dosyası yüklersiniz. Ardından, ayarları doldurmak için ayrıştırılan değerleri kullanırsınız.

Başarıyla kullandığım bir strateji:

  • Varsayılan yükle defaults.ini dosya
  • Makine adını kontrol edin ve en kısa eşleşmeden en uzun eşleşmeye kadar ters FQDN ile eşleşen tüm dosyaları yükleyin (böylece yükledim net.ini, sonra net.domain.ini,net.domain.webserver01.ini , her biri muhtemelen önceki değerlerini geçersiz kılma). Bu hesap ayrıca geliştiricilerin makineleri için, her biri yerel geliştirme için tercih edilen veritabanı sürücüsünü vb.
  • Bildirilen bir "küme adı" olup olmadığını ve bu durumda cluster.cluster_name.iniveritabanı ve önbellek IP'leri gibi şeyleri tanımlayabilecek yük olup olmadığını kontrol edin

Bununla başarabileceğiniz bir şeye örnek olarak, daha sonra hostname: %(subdomain).whatever.netdjango'nun çalışması için gerekli tüm ana bilgisayar adlarını ve çerez öğelerini tanımlamak için varsayılan ayarlarda (as ) kullanılan bir "alt alan" değeri tanımlayabilirsiniz.

Bu alabilirim KURU, çoğu (mevcut) dosyaları sadece 3 veya 4 ayar vardı. Bunun üzerine müşteri yapılandırmasını yönetmek zorunda kaldım, bu yüzden müşteri başına bir veya daha fazla ek yapılandırma dosyası kümesi (veritabanı adları, kullanıcılar ve parolalar, atanan alt alan adı vb.) Vardı.

Bunu düşük veya gerektiği kadar ölçekleyebilir, sadece ortam başına yapılandırmak istediğiniz anahtarları yapılandırma dosyasına koyarsınız ve yeni bir yapılandırmaya ihtiyaç duyduğunuzda, önceki değeri varsayılan yapılandırmaya koyar ve geçersiz kılar Gerektiğinde.

Bu sistem güvenilir olduğunu kanıtlamıştır ve sürüm kontrolü ile iyi çalışır. Uzun süre, iki ayrı uygulama kümesini (makine başına django sitesinin 15 veya daha fazla ayrı örneği) yönetmek için kullanıldı, burada 50'den fazla müşteri, kümelerin sistem yöneticisinin ruh haline bağlı olarak boyutu ve üyeleri değiştiriyordu. .


1
Ayarları ini'den Django'nun ayarlarına nasıl yüklediğinize dair bir örneğiniz var mı?
kaleissin

Bkz. Docs.python.org/2/library/configparser.html . İle bir ayrıştırıcı yükleyebilir, config = ConfigParser.ConfigParser() sonra dosyalarınızı okuyabilir config.read(array_of_filenames)ve kullanarak değerleri alabilirsiniz config.get(section, option). Bu yüzden önce yapılandırmanızı yüklersiniz ve sonra ayarları için değerleri okumak için kullanırsınız.
yeniden yazıldı

5

Laravel ile de çalışıyorum ve oradaki uygulamayı seviyorum. Taklit etmeye ve T. Stone tarafından önerilen çözümle birleştirmeye çalıştım (yukarıya bakın):

PRODUCTION_SERVERS = ['*.webfaction.com','*.whatever.com',]

def check_env():
    for item in PRODUCTION_SERVERS:
        match = re.match(r"(^." + item + "$)", socket.gethostname())
        if match:
            return True

if check_env():
    PRODUCTION = True
else:
    PRODUCTION = False

DEBUG = not PRODUCTION

Belki böyle bir şey size yardımcı olacaktır.


4

Settings.py'nin canlı bir kod dosyası olduğunu unutmayın. DEBUG'ın üretime geçmediğini varsayarsak (ki bu en iyi uygulamadır), şöyle bir şey yapabilirsiniz:

if DEBUG:
    STATIC_PATH = /path/to/dev/files
else:
    STATIC_PATH = /path/to/production/files

Oldukça basit, ama teorik olarak, sadece DEBUG değerine veya kullanmak istediğiniz diğer değişken veya kod kontrolüne dayanan herhangi bir karmaşıklık seviyesine yükselebilirsiniz.


4

Projelerimin çoğu için aşağıdaki kalıbı kullanıyorum:

  1. Tüm ortamlar için ortak ayarları sakladığım settings_base.py dosyasını oluştur
  2. Ben özel gereksinimleri ile yeni bir ortam kullanmak için ihtiyaç duyarsan ben yeni ayarlar dosyası oluşturmak (örneğin. Settings_local.py) hangi settings_base.py ve bindirilmesi devralır içerikleri / düzgün ayarlar değişkenlerini ekler ( from settings_base import *)

(Sadece --settings komut seçeneğini kullanın dosyası özel ayarlarla manage.py çalıştırmak için: manage.py <command> --settings=settings_you_wish_to_use.py)


3

Bu soruna benim çözümüm de burada daha önce belirtilen bazı çözümlerin bir karışımı:

  • Dev local_settings.pyiçeriğine sahip bir dosya tutmak USING_LOCAL = TrueveUSING_LOCAL = False eşya tutuyorum
  • In settings.pyO dosya üzerinde bir ithalat yapmak için USING_LOCALayarı

Daha sonra çevreye bağlı tüm ayarlarımı buna bağlıyorum:

DEBUG = USING_LOCAL
if USING_LOCAL:
    # dev database settings
else:
    # prod database settings

Bunu, ayarlarımın tek bir dosyada yapılandırılmasını sağlayabildiğim için, bakımım gereken iki ayrı settings.py dosyasına sahip olmayı tercih ediyorum. Bu şekilde, bir ayarı güncellediğimde, her iki ortam için de yapmayı unutmayın.

Tabii ki her yöntemin dezavantajları vardır ve bu bir istisna değildir. Buradaki sorun, local_settings.pydeğişiklikleri ürettiğimde dosyanın üzerine yazamam, yani tüm dosyaları körü körüne kopyalayamıyorum, ancak bu yaşayabileceğim bir şey.


3

Yukarıda biraz daha kısa bulduğum jpartogi'nin bir varyasyonunu kullanıyorum:

import platform
from django.core.management import execute_manager 

computername = platform.node()

try:
  settings = __import__(computername + '_settings')
except ImportError: 
  import sys
  sys.stderr.write("Error: Can't find the file '%r_settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file local_settings.py does indeed exist, it's causing an ImportError somehow.)\n" % (computername, __file__))
  sys.exit(1)

if __name__ == "__main__":
  execute_manager(settings)

Temelde her bilgisayarda (geliştirme veya üretim) dinamik olarak yüklenen uygun hostname_settings.py dosyasına sahibim.



3

1 - Uygulamanızın içinde yeni bir klasör ve ad ayarları oluşturun.

2 - Şimdi __init__.pyiçinde yeni bir dosya oluşturun ve içine yazın

from .base import *

try:
    from .local import *
except:
    pass

try:
    from .production import *
except:
    pass

3 - Ayarlar klasörü adında üç yeni dosya oluşturun local.pyve production.pyve base.py.

4 - İçeride base.py, önceki settings.pyklasörün tüm içeriğini kopyalayın ve farklı bir şeyle yeniden adlandırın old_settings.py.

5 - base.py'de BASE_DIR yolunuzu yeni ayar yolunuzu gösterecek şekilde değiştirin

Eski yol-> BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

Yeni yol -> BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

Bu şekilde, proje yönetimi üretim ve yerel kalkınma arasında yapılandırılabilir ve yönetilebilir.


2

settingsFarklı ortamlarda farklı yapılandırma kullanmak için farklı ayarlar dosyası oluşturun. Ve dağıtım komut dosyanızda, sunucuyu farklı ortamlarda --settings=<my-settings.py>farklı ayarlar kullanabileceğiniz bir parametre kullanarak başlatın .

Bu yaklaşımı kullanmanın faydaları :

  1. Ayarlarınız her ortama göre modüler olacaktır

  2. master_settings.pyTemel yapılandırmayı içeren içeriğe aktarabilir ve environmnet_configuration.pyo ortamda değiştirmek istediğiniz değerleri geçersiz kılabilirsiniz.

  3. Büyük bir ekibiniz varsa, her geliştiricinin local_settings.pysunucu yapılandırmasını değiştirme riski olmadan kod deposuna ekleyebilecekleri kendi geliştiricileri olabilir . Sen bu yerel ayarları ekleyebilir .gitnorekullanırsanız git ya .hginoreeğer Mercurial için Sürüm Kontrolü (veya başka). Bu şekilde yerel ayarlar, onu temiz tutan gerçek kod tabanının bir parçası bile olmaz.


2

Ayarlarım aşağıdaki gibi bölündü

settings/
     |
     |- base.py
     |- dev.py
     |- prod.py  

3 ortamımız var

  • dev
  • sahneleme
  • üretim

Şimdi açık bir şekilde evreleme ve üretim mümkün olan en yüksek benzer ortama sahip olmalıdır. Biz deprod.py ikisini de sakladık.

Ama çalışmakta olan sunucunun bir üretim sunucusu olduğunu tespit etmem gereken bir durum vardı. @ T. Stone'un cevabı şu şekilde çek yazmama yardımcı oldu.

from socket import gethostname, gethostbyname  
PROD_HOSTS = ["webserver1", "webserver2"]

DEBUG = False
ALLOWED_HOSTS = [gethostname(), gethostbyname(gethostname()),]


if any(host in PROD_HOSTS for host in ALLOWED_HOSTS):
    SESSION_COOKIE_SECURE = True
    CSRF_COOKIE_SECURE = True  

1

Manage.py içinde onu ayırdım ve iki ayrı ayar dosyası oluşturdum: local_settings.py ve prod_settings.py.

Manage.py'de sunucunun yerel sunucu mu yoksa üretim sunucusu mu olduğunu kontrol ediyorum. Yerel bir sunucuysa, local_settings.py'yi yükler ve bir üretim sunucusuysa prod_settings.py'yi yükler. Temel olarak şöyle görünecektir:

#!/usr/bin/env python
import sys
import socket
from django.core.management import execute_manager 

ipaddress = socket.gethostbyname( socket.gethostname() )
if ipaddress == '127.0.0.1':
    try:
        import local_settings # Assumed to be in the same directory.
        settings = local_settings
    except ImportError:
        import sys
        sys.stderr.write("Error: Can't find the file 'local_settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file local_settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
        sys.exit(1)
else:
    try:
        import prod_settings # Assumed to be in the same directory.
        settings = prod_settings    
    except ImportError:
        import sys
        sys.stderr.write("Error: Can't find the file 'prod_settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file prod_settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
        sys.exit(1)

if __name__ == "__main__":
    execute_manager(settings)

Ayarlar dosyasının içinde çok sayıda ifs yapmak yerine ayarlar dosyasını iki ayrı dosyaya ayırmanın daha kolay olduğunu gördüm.


1

İsterseniz farklı dosyayı korumak için alternatif olarak: Kodları yerelden sunucuya göndermek için git veya başka bir VCS kullanıyorsanız, yapabileceğiniz ayar dosyası .gitignore'a eklemek.

Bu, her iki yerde de sorunsuz bir şekilde farklı içeriğe sahip olmanızı sağlayacaktır. SO sunucuda settings.py'nin bağımsız bir sürümünü yapılandırabilirsiniz ve yerelde yapılan değişiklikler sunucuya yansımayacaktır veya tersi de geçerlidir.

Buna ek olarak, github'dan settings.py dosyasını da kaldıracak, birçok yeni başlayanın gördüğü büyük hata.



0

Bence en iyi çözüm @T tarafından öneriliyor. Stone, ama neden Django'da DEBUG bayrağını kullanmadığımı bilmiyorum. Web sitem için aşağıdaki kodu yazıyorum:

if DEBUG:
    from .local_settings import *

Her zaman basit çözümler karmaşık olanlardan daha iyidir.


-2

Yanıtları burada çok yararlı buldum. (Bu daha kesin bir şekilde çözüldü mü? Son yanıt bir yıl önceydi.) Listelenen tüm yaklaşımları düşündükten sonra, burada listelenmeyen bir çözüm buldum.

Benim kriterlerim:

  • Her şey kaynak kontrolünde olmalıdır. Etrafta yalan söyleyen ufak tefek parçaları sevmiyorum.
  • İdeal olarak, ayarları tek bir dosyada saklayın. Onlara doğru bakmazsam bir şeyler unuturum :)
  • Kullanılacak manuel düzenleme yok. Tek bir kumaş komutuyla test / itme / konuşlandırma yapabilmelidir.
  • Geliştirme ayarlarını üretime sızmaktan kaçının.
  • "Standart" (* öksürük *) Django düzenine mümkün olduğunca yakın tutun.

Ben ana makinede anahtarlama bazı mantıklı düşündüm, ama sonra farklı farklı ayarlar burada gerçek sorunu düşündüm ortamlar ve bir aha anı vardı. Bu kodu settings.py dosyamın sonuna koydum :

try:
    os.environ['DJANGO_DEVELOPMENT_SERVER'] # throws error if unset
    DEBUG = True
    TEMPLATE_DEBUG = True
    # This is naive but possible. Could also redeclare full app set to control ordering. 
    # Note that it requires a list rather than the generated tuple.
    INSTALLED_APPS.extend([
        'debug_toolbar',
        'django_nose',
    ])
    # Production database settings, alternate static/media paths, etc...
except KeyError: 
    print 'DJANGO_DEVELOPMENT_SERVER environment var not set; using production settings'

Bu şekilde, uygulama varsayılan olarak üretim ayarlarına geçer, bu da geliştirme ortamınızı açıkça "beyaz listeye eklediğiniz" anlamına gelir. Ortam değişkenini yerel olarak ayarlamayı, başka türlü olmasından çok daha güvenlidir ve üretimde bir şey ayarlamayı ve bazı geliştirici ayarlarının kullanılmasına izin vermeyi unutursunuz.

Yerel olarak gelişirken, kabuktan veya bir .bash_profile dosyasında veya herhangi bir yerde:

$ export DJANGO_DEVELOPMENT_SERVER=yep

(Ya da Windows'ta geliştiriyorsanız, Denetim Masası'ndan veya bugünlerde ne denirse ayarlayın ... Windows her zaman ortam değişkenlerini ayarlayabileceğiniz kadar belirsiz hale getirdi.)

Bu yaklaşımla, geliştirici ayarlarının tümü tek bir (standart) yerde bulunur ve gerektiğinde üretim ayarlarını geçersiz kılar. Geliştirme ortamlarında meydana gelen herhangi bir sapma, üretim üzerinde hiçbir etkisi olmadan kaynak kontrolünü sağlamak için tamamen güvenli olmalıdır.


Sadece farklı yapılandırma dosyalarını korumak ve DJango standart env değişkeni kullanarak seçim yapmak daha iyidir DJANGO_SETTINGS_MODULE
Rob Grant
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.