3

Apache vhost 構成ファイルから環境変数を読み取り、それらを Django 設定に保存したいと考えています。

Django 1.7 に更新する前はすべて問題ありませんでしたが、現在は壊れています。

私が呼び出すと、問題は私のwsgi.pyスクリプトにあるようです

_application = get_wsgi_application()

環境変数が設定される前に構成ファイルを読み取るためです。

Django 1.7 でこれを行う別の方法はありますか?

/etc/apache2/sites-enabled/mysyte.conf には次のものがあります。

<VirtualHost *:80>

    ...

    SetEnv SECRET_KEY ...
    SetEnv EMAIL_HOST ...
    SetEnv EMAIL_HOST_PASSWORD ...
    SetEnv EMAIL_HOST_USER ...
    SetEnv EMAIL_PORT 25
    ...

私のwsgi.pyで:

import os
from os.path import abspath, dirname
from sys import path

SITE_ROOT = dirname(dirname(abspath(__file__)))
path.append(SITE_ROOT)

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "locacle.settings.production")

_application = get_wsgi_application()

def application(environ, start_response):
    for key, value in environ.items():
        if isinstance(environ[key], str):
            os.environ[key] = environ[key]

    return _application(environ, start_response)

私のsettings.pyには次のものがあります:

from os import environ

from base import *

def get_env_setting(setting):
    """ Get the environment setting or return exception """
    try:
        return environ[setting]
    except KeyError:
        error_msg = "Set the %s env variable" % setting
        raise ImproperlyConfigured(error_msg)


EMAIL_HOST = get_env_setting('EMAIL_HOST')

...

これは、ログ ファイルが報告する内容です。

...
mod = importlib.import_module(self.SETTINGS_MODULE)
File "/usr/lib/python2.7/importlib/__init__.py", line 37, in import_module
  __import__(name)
File "/home/www/.../settings/production.py", line 34, in <module>
  EMAIL_HOST = get_env_setting('EMAIL_HOST')
File "/home/www/...settings/production.py", line 21, in get_env_setting
  raise ImproperlyConfigured(error_msg)
ImproperlyConfigured: Set the EMAIL_HOST env variable
...
4

1 に答える 1

4

残念ながら、あなたがここでやろうとしていることは本質的に壊れやすく、以前のバージョンの Django では幸運な偶然によってのみ機能し、Django 1.7 または将来のバージョンの Django では機能しません。(更新:WSGIは通常そうではありませんが、「シェルショック」bashバグに対して脆弱になる可能性もあります。)

基本的な問題は、WSGI 環境がリクエストごとにしか利用できないことですが、それに基づいて Django プロセスのグローバル構成を設定しようとしています。これは非効率的で概念的に壊れています (リクエストが来るたびに OS 環境変数を何度も再設定するのはなぜですか? 異なるリクエストが異なる WSGI 環境を持っている場合はどうなるでしょうか?)、Django が待機する場合にのみ機能します。最初のリクエストが到着するまで、自分自身を構成します。

しかし、以前のバージョンでは、Django の起動シーケンスの予測不可能なタイミングと順序が問題を引き起こしました。たとえば、ローカル開発で runserver を使用する場合、Django は検証チェックのために自分自身を熱心に構成しますが、実稼働環境では自分自身を遅延して構成するだけであり (これに依存していました)、インポートが異なる順序で発生し、 runserver では再現できない循環インポートが本番環境で発生します。

Django 1.7 には、これらの問題に対処するために改良された起動シーケンスが含まれており、起動シーケンスを予測可能にし、開発と本番の間で一貫性を持たせ、ユーザーが起動時に実行するコードを ( 経由でAppConfig.ready()) 明示的に登録できるようにします。これの副作用は、最初のリクエストが来るまで待たずに、プロセスの起動時に (具体的には in の呼び出しdjango.setup()で) 設定が構成されることです。get_wsgi_application()

このサーバーで Django サイトを 1 つだけ実行している場合は、構成を Apache 構成ではなく通常の環境変数に移動するだけでSetEnv、問題全体を回避できます。

単一の Apache サーバーを介して異なる構成を必要とする複数の Django サイトを実行している場合、それは機能しません。その場合、おそらく Apache に詳しい人がいてmod_wsgi、信頼できる方法で Apache 構成から Django プロセスに環境変数を渡す方法についてアドバイスをくれるでしょう。個人的には、プロセス モデル (実際には、プロセス モデル。構成方法によっては複数あるため) はmod_wsgi、1 つのサーバーで複数の個別に構成されたサイトを実行しようとすると、混乱し、エラーが発生しやすくなります。gunicorn や uwsgi などの専用の WSGI サーバーを使用し、それに Apache (または nginx) プロキシを使用する方が簡単だと思います。そうすれば、別々の OS 環境で複数の gunicorn/uwsgi プロセスを簡単に実行できます。

于 2014-09-12T17:07:40.070 に答える