2013-11-03 26 views
15

Django'nun gizli anahtarını ve DB'yi yaygın olarak önerildiği gibi çevresel değişkenlere ayırmaya çalışıyorum, böylece yerel/üretim sunucuları arasında aynı kod tabanlarını kullanabilirim.Erişim Apache SetEnv değişkeni Django wsgi.py dosyasından

Çalıştığım sorun, Apache + mod_wsgi çalıştıran üretim sunucusundaki ortam değişkenlerini doğru şekilde ayarlayıp okuyor.

Apache kullanıcı olarak çalıştırılmadığından, kullanıcı profilimde ayarlanmış olan var olmayan seçenekler mevcut değildir. Kapsam, bir şekilde farklı olduğundan, SetEnv ile Sanal Hosts dosyasında ayarlanan varlar kullanılamaz.

Bir çözüm ile this blog yol açan bir çift 1, 2 SO yanıtlarını okudum.

Ben benzeyen bir wsgi.py dosyasını kullanmak Django güncel sürümleri, çözüm nasıl uygulanacağını bilemiyorum: başvurabilirim nasıl

import os 
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings") 

from django.core.wsgi import get_wsgi_application 
application = get_wsgi_application() 

o wsgi.py dosyasına blog çözümü ya da Django'nun onlara ulaşabileceği env-vars'ı saklamak için daha iyi bir yer var mı?

cevap

10

FWIW. İnce taneli konfigürasyon ayarları için ortam değişkenlerine güvenmek genel olarak iyi bir fikir değildir. Bunun nedeni, tüm WSGI barındırma ortamlarının veya ticari PaaS tekliflerinin kavramı desteklememesidir. İnce taneli ortamlar için ortam değişkenlerini kullanmak, belirli bir PaaS teklifine sizi doğrudan kodlanmış bir ortam değişkeninin doğrudan kodunuza doğrudan gömdüğü belirli bir PaaS teklifine kilitleyebilir. Burada, söz konusu ortam değişkeninin adlandırma kuralının bu barındırma hizmetine özgü olduğu belirtilir. Bu nedenle, ortam değişkenlerinin kullanımı belirli servisler tarafından zorlanmasına rağmen, WSGI uygulamanızın taşınabilirliğini azaltacak ve dağıtım mekanizmaları arasında geçişi zorlaştıracağından, her zaman ortam değişkenlerine bağımlı olmak konusunda dikkatli olun.

Tüm söylediğim, bahsettiğiniz blog gönderisinde genellikle yardımcı olmayacaktır. Bunun nedeni, Apache'de SetEnv kullanılarak ayarlanan istek başına WSGI ortam ayarlarına dayalı olarak her istekte işlem ortamı değişkenlerinin ayarlanmasının yanlış bir hile kullanmasıdır. Bu, ortam değişkenlerinin değerleri URL içeriğine bağlı olarak farklılık gösterebilirse, çok iş parçacığı yapılandırmasında çeşitli sorunlara neden olabilir. Django söz konusu olduğunda, Django ayar modülünün normalde herhangi bir istekte bulunulmadan önce içe aktarılacağı için yardımcı olmaz, bu da ortam değişkenlerinin gereken zamanda mevcut olmayacağı anlamına gelir.

Tüm bu yapılandırma yapılandırması, daha iyi bir yöntem yapmanın gerekliliğine ihtiyaç duymaktadır, ancak açıkçası daha çok bir WSGI dağıtım stratejisine uyum sağlamak için barındırma hizmetleri bir şeyleri değiştirmeyeceği için çoğunlukla kayıp bir nedendir. İşlerini yapmışlar, müşterilerini halihazırda yaptıkları şekilde kilitlemiş ve daha iyi bir şekilde var olsalar bile, kendileri için iş yaratmaya ve bir şeyleri değiştirmeye dayanmamaktadırlar. Her neyse, 'bilgisayar bilimlerindeki tüm problemler bir başka indirgeme seviyesiyle çözülebilir'. (http://en.wikipedia.org/wiki/Indirection) ve burada yapabileceğiniz şey budur.

Uygulama arama ortam değişkenleriniz yok. Konfigürasyon ayarlarını almak için bir API kullanmanın bir yolunu içeren konuşlandırmaya özgü bir Python konfigürasyon modülünü içe aktarın. Bu yapılandırma modülü, gerçek ayarları dağıtım mekanizmasına dayalı olarak almanın farklı yollarını uygulayacaktır. Bazı durumlarda, ortam değişkenlerinden gelen değerleri alabilir. Apache/mod_wsgi ile olduğu gibi, değerler bu yapılandırma modülünde olabilir veya ini, json veya yaml formatı olabilecek ayrı bir yapılandırma dosyasından okunabilir.Bir API sağlamada, farklı PaaS teklifleri tarafından kullanılan farklı adlara yapılandırma ayarlarının adlarını da gösterebilir.

Bu yapılandırma modülünün uygulama kodunuzun bir parçası olması gerekmez, ancak hedef sistemdeki '/ etc /' alt dizinine manuel olarak yerleştirilebilir. Uygulamanızın görebilmesi için Python modülü arama yolunu ayarlamanız yeterlidir. Tüm sistem, WSGI dağıtımı için daha iyi bir standardın parçası olarak oldukça zarif hale getirilebilirdi, ancak dediğim gibi, mevcut PaaS tekliflerinin böyle bir standardı kullanmak için değişme olasılığı düşük olduğu zaman böyle bir şeyi yaratmanın zor işini yapmak için çok az teşvik. .

+0

Başka bir soruda @Graham Dumpleton, kullanılacak ayar dosyasından geçmek için temiz bir yol önerir: http://stackoverflow.com/a/25496668/3189 –

22

Eğer Graham'ın cevabı başka biri tarafından hayal kırıklığına uğrarsa, asıl soru için gerçekten işe yarayan bir çözüm. Özellikle kendi hosting ortamımı yapılandıracağım ve istediğim her şeyi yapabileceğime göre, Apache'den çevresel değişkenleri son derece kullanışlı ve pratik bir hale getirmeyi düşünüyorum. (Django 1.5.4 test)

wsgi.py minör Dikkat çekici

from django.core.handlers.wsgi import WSGIHandler 

class WSGIEnvironment(WSGIHandler): 

    def __call__(self, environ, start_response): 

     os.environ['SETTINGS_CONFIG'] = environ['SETTINGS_CONFIG'] 
     return super(WSGIEnvironment, self).__call__(environ, start_response) 

application = WSGIEnvironment() 

, şu anda sadece WSGIHandler() döndürür django.core.wsgi.get_wsgi_application geleceği geçirmez yöntem kaybederler. WSGIHandler.__call__ yöntemi her zaman güncelleştirilir ve Django da güncelleştirirseniz, bağımsız değişkenler değiştiğinde WSGIEnvironment sınıfını güncelleştirmeniz gerekebilir. Bu kolaylık için ödemek için çok küçük bir ceza düşünün.

+0

django 1.6.5 ile test edilmiş ve çalışıyor ... – jliendo

+1

Django 1.8'den itibaren .2 (ve muhtemelen daha eski bir sürümü), 'get_wsgi_application()' ek bir satıra sahiptir: 'django' django.setup()', 'döndürün; WSGIHandler()' – Izkata

+1

@Izkata tam bir örnek verebilir misiniz? şeyler yapmak için güncellenmiş bir yol? – ButtersB

4

Burada, get_wsgi_application olarak geleceğe hazır olarak kullanılabilecek alternatif bir çözüm var. Hatta Django başlatma işleminizde kullanılacak ortam değişkenlerini ayarlamanıza da izin verir. mod_wsgi süreçlerini yöneten nasıl

# in wsgi.py 

KEYS_TO_LOAD = [ 
    # A list of the keys you'd like to load from the WSGI environ 
    # into os.environ 
] 

def loading_app(wsgi_environ, start_response): 
    global real_app 
    import os 
    for key in KEYS_TO_LOAD: 
     try: 
      os.environ[key] = wsgi_environ[key] 
     except KeyError: 
      # The WSGI environment doesn't have the key 
      pass 
    from django.core.wsgi import get_wsgi_application 
    real_app = get_wsgi_application() 
    return real_app(wsgi_environ, start_response) 

real_app = loading_app 

application = lambda env, start: real_app(env, start) 

% 100 net değilim, ama çok sık WSGI uygulamayı yeniden yüklemez varsayalım. Eğer öyleyse, Django'yu başlatmadaki performans cezası, ilk talepte sadece bir kez gerçekleşecektir. Eğer Django başlatılıyor önce ortam değişkenlerini kurmak için gerekmiyorsa

Alternatif olarak, kullanabilirsiniz:

Django 1.11 için
# in wsgi.py 

KEYS_TO_LOAD = [ 
    # A list of the keys you'd like to load from the WSGI environ 
    # into os.environ 
] 

from django.core.wsgi import get_wsgi_application 
django_app = get_wsgi_application() 

def loading_app(wsgi_environ, start_response): 
    global real_app 
    import os 
    for key in KEYS_TO_LOAD: 
     try: 
      os.environ[key] = wsgi_environ[key] 
     except KeyError: 
      # The WSGI environment doesn't have the key 
      pass 
    real_app = django_app 
    return real_app(wsgi_environ, start_response) 

real_app = loading_app 

application = lambda env, start: real_app(env, start) 
+0

Çalışıyor, ama özlemişsiniz: '' os.environ.setdefault ("DJANGO_SETTINGS_MODULE", "project.settings") '' – NBajanca

+0

Çözümünüz ayrıca Django 1.10'da da çalışıyor – ozw1z5rd

0

:

Apache yapılandırma:

<VirtualHost *:80 > 
    ... 
    SetEnv VAR_NAME VAR_VALUE 
</VirtualHost> 

wsgi.py:

İlgili konular