このドキュメントの Django のバージョンにはセキュリティ上の脆弱性があるため、すでにサポートが終了されています。新しいバージョンにアップグレードしてください!最新の Django のバージョンのドキュメントはこちら

Django v1.0 documentation

Apache と mod_python で Django を動かす

revision-up-to:8961 (1.0)

Django をプロダクションサーバ上で動かす設定として、現状では Apachemod_python の組み合わせを推奨しています。

mod_python は mod_perl とよく似ていて (影響を受けていて)、 Apache の中に Python を埋め込み、サーバ起動時に Python のコードをメモリ上に読み込みます。 読み込まれたコードは Apache のプロセスが生きている間ずっと残るので、他のや りかたに比べて明確なパフォーマンスの向上につながります。

Django を mod_python で動かす場合、 Apache 2.x と mod_python 3.x が必要です。 また、 Apache を使う場合、 worker MPM ではなく prefork MPM を使うよう 勧めます。

興味があれば FastCGI, SCGI, AJP で Django を動かす <howto-deplyment-fastcgi> もどうぞ (SCGI と AJP もカバーしています)。

基本的な設定

Django を mod_python で動かすようにするには、まず Apache がインストールされ、 mod_python モジュールが有効になっていることを確かめます。

次に、 httpd.conf ファイルを編集し、以下のような設定を追加します:

<Location "/mysite/">
    SetHandler python-program
    PythonHandler django.core.handlers.modpython
    SetEnv DJANGO_SETTINGS_MODULE mysite.settings
    PythonOption django.root /mysite
    PythonDebug On
</Location>

mysite.settings は、 Django プロジェクトの設定ファイルを指す Python import パスになるよう、自分の環境に合わせて置き換えて下さい。

この設定は、 Apache に 「/mysite/ の下の全ての URL は mod_python で処理し、 処理には Django mod_python ハンドラを使うように」命令します。また、 DJANGO_SETTINGS_MODULE を渡して、 mod_python にどこに設定ファイルがあるのか教えます。

Django 1.0 で新たに登場しました: PythonOption django.root ... が新たに登場しました。

mod_python は、サイトを /mysite/ プレフィクスの下で提供していることを自 動的に検出できないので、 PythonOption django.root ... を使ってハンドラ に通知してやる必要があります。この行に設定する値は、 <Location ...> の引数と一致していなければなりません。 django.root を設定すると、 Django はリクエストの URL から django.root に設定されたプレフィクスを除 去した上で URLConf のパターンマッチングを行います。このため、後でサイト を /mysite2 に動かした際に、 djnago.root だけを変更すればよくなりま す。

django.root を使う場合、必ず、プレフィクスを除去した後の URL がスラッシュ で開始するようにしてください。 そうでないと、先頭にスラッシュの入る URLConf の設定があった場合、パターンマッチングがうまくいきません。上の例では、 /mysite/admin//admin/ に変えたいので、先頭から除去すべきなのは /mysite です。従って、 django.root の値を /mysite にしているの です。この場合、 /mysite/ (末尾にスラッシュがついている) にしてしまうと、 エラーをひき起こすでしょう。

上の例では <Directory> ではなく <Location> ディレクティブを使って います。前者はファイルシステム上の場所を指定するのに使い、後者はウェブサイ トのURL 構造上の場所を指定するのに使います。従って、 <Directory> を使っ た指定は意味をなさないのです。

また、 Django プロジェクトがデフォルトの PYTHONPATH 上になければ、以下 のような設定を mod_python に教えておく必要があります:

<Location "/mysite/">
    SetHandler python-program
    PythonHandler django.core.handlers.modpython
    SetEnv DJANGO_SETTINGS_MODULE mysite.settings
    PythonOption django.root /mysite
    PythonDebug On
    PythonPath "['/path/to/project'] + sys.path"
</Location>


PythonPath "['/path/to/project'] + sys.path"

PythonPath には、アプリケーションから import したいモジュールの各々の 親ディレクトリを入れなければなりません。また、 DJANGO_SETTINGS_MODULE の親ディレクトリも入れねばなりません。対話シェル を使う場合に Python パスを設定するのと同じです。何かモジュールを import す る際には、Python は必ず sys.path の各ディレクトリを順に調べ、その下から 該当モジュールを import しようと試み、 import に成功するまで探索を続けます。

分かりやすくするために例を挙げましょう。アプリケーションを /usr/local/django-apps/ の下に配置しているとします (例えば、 /usr/local/django-apps/weblog/ のようにです) 。そして、 mysite プロ ジェクトが /var/www/ 下にあるとしましょう。上の例のように DJANGO_SETTINGS_MODULE を設定している場合に は、 PythonPath を以下のように書かねばなりません:

PythonPath "['/usr/local/django-apps/', '/var/www'] + sys.path"

これで、 import weblogimport mysite.settings が正しく動作します。 コード中で import blogroll していて、 blogrollweblog/ ディ レクトリの下にあるようなら、 /usr/local/django-apps/weblog/PythonPath に加えねばなりません。 import したいモジュールの 親ディレクトリ を Python パスに入れねばならないことに注意してください。

Note

Windows を使っているなら、パスの表記に注意してください。 Windows は通常 バックスラッシュをネイティブのパス区切り文字に使いますが、それでもスラッ シュを使ってパスを表記するよう進めます。 Apache はスラッシュをプラット フォームネイティブのパス区切り文字に変換する方法を知っているので、スラッ シュを使った方が、可搬性や視認性を持たせられるのです。 (それに、バックス ラッシュの二重エスケープのようなトリッキーな問題を回避できます)。

Windows システムでも、以下のパス表記を利用できます:

PythonPath "['c:/path/to/project'] + sys.path"

また、 PythonAutoReload Off のようなディレクティブを設定して、パフォー マンスを向上させられます。使えるオプションのリストは mod_python のドキュメント を参照してください。

注意しなければならないのは、プロダクションサーバでは、 PythonDebug Off を設定すべきであるということです。 PythonDebugOn に設定されたま まだと、 mod_python に不具合が生じたときに、恰好の悪い (そして赤裸々な) Python トレースバックを表示してしまいます。

Apache を再起動しましょう。 /mysite/ やその下の URL へのリクエストが Django によって提供されているはずです。 Django の URLconf は /mysite/ を切り取りらず、完全な URL を渡すことに注意して下さい。

Django で作られたサイトを mod_python 上で運営している場合、 Python コードに 対して変更を加える度に Apache を再起動する必要があります。

ひとつの Apache に複数の Django をインストールする

ひとつの Apache に複数の Django をインストールするのは簡単です。 VirtualHost を使って、以下のようにするだけです:

NameVirtualHost *

<VirtualHost *>
    ServerName www.example.com
    # ...
    SetEnv DJANGO_SETTINGS_MODULE mysite.settings
</VirtualHost>

<VirtualHost *>
    ServerName www2.example.com
    # ...
    SetEnv DJANGO_SETTINGS_MODULE mysite.other_settings
</VirtualHost>

一つの VirtualHost 設定の中に複数の Django をインストールしたい場合、 mod_python のキャッシュが Django の動作を台無しにしないように特に気を配る必 要があります。 PythonInterpreter ディレクティブを使って、 <Location> ディレクティブごとに別のインタプリタを使うようにしてください:

<VirtualHost *>
    ServerName www.example.com
    # ...
    <Location "/something">
        SetEnv DJANGO_SETTINGS_MODULE mysite.settings
        PythonInterpreter mysite
    </Location>

    <Location "/otherthing">
        SetEnv DJANGO_SETTINGS_MODULE mysite.other_settings
        PythonInterpreter othersite
    </Location>
</VirtualHost>

PythonInterpreter の値は、二つの Location ブロックの間で違う値にさ えなっていれば何でもかまいません。

mod_python 上で開発用サーバを動かす

開発用サーバに mod_python を使う場合、コードを変更する度にサーバを再起動す るようなやんちゃは避けられます。 MaxRequestsPerChild 1 をアパッチの httpd.conf ファイルに指定し、Apache にリクエストごとに全てをリロードさ せてください。とはいえ、これをプロダクションサーバでやらないでください。さ もないと、 Django の恩恵が失われてしまいます。

あなたが print 文を散りばめてデバッグするタイプのプログラマなら、 print 文は mod_python では何の効果も及ぼさないということに注意しましょ う。 print 文を使っても、 Apache のログには何も出力されません。 mod_python を使った設定でデバッグ情報を出力したいのなら:

assert False, the_value_i_want_to_see

のようにするか、ページのテンプレートにデバッグ情報を追加してください。

メディアファイルの提供

Django は、自分ではメディアファイルの提供を行わず、ユーザの選んだ Web サー バにその仕事を任せます。

メディアの提供には、別のウェブサーバ、すなわち Django を動かしていないサー バを使うよう勧めます。お勧めはいくつかあります:

とはいえ、Django を動作させているのと同じ Apache の VirtualHost でメディ アファイルを提供せざるを得ない場合には、以下のようにして特定の場所でだけ mod_python を切ります:

<Location "/media">
    SetHandler None
</Location>

Location ディレクティブの引数を、メディアファイルを置いている場所のルー ト URL に置き換えて下さい。 <LocationMatch> を使って、正規表現に一致さ せるようにもできます。

以下の例では、 Django をサイトのルートで設定し、 media サブディレクトリ の下と、 .jpg.gif 、および .png で終わる URL だけでは明示的 に Django を無効にしています:

<Location "/">
    SetHandler python-program
    PythonHandler django.core.handlers.modpython
    SetEnv DJANGO_SETTINGS_MODULE mysite.settings
</Location>

<Location "/media">
    SetHandler None
</Location>

<LocationMatch "\.(jpg|gif|png)$">
    SetHandler None
</LocationMatch>

admin ファイルの提供

Django の開発サーバは自動的に admin メディアファイルを提供しますが、それ以 外の設定ではこれはあてはまりません。admin ファイルを提供するには、 Apache なりその他のメディアサーバなりで設定を行う必要があります。

admin ファイルは Django 配布物の (django/contrib/admin/media) ディ レクトリ下にあります。

お勧めのアプローチは二つあります:

  1. ドキュメントルートから admin メディアファイルへのシンボリックリンク を作ります。そうすれば、リンクを張った Django 関係のファイル (コード テンプレート) を一箇所にまとめられるので、自分のコードを svn update するだけで admin テンプレートを最新の状態に保てます。
  2. または、 admin メディアファイルをコピーして Apache のドキュメントルー トに入れます。

mod_python 上で "egg" パッケージを使う

Django を Python egg でインストールしたり、 Django から egg 化されたモジュー ルを使っている場合、いくつか追加の設定が必要です。プロジェクト中 (か、どこ か import できる場所) にファイルを作り、以下の内容を入れておきます:

import os
os.environ['PYTHON_EGG_CACHE'] = '/some/directory'

/some/directory は Apache httpd を動作させているプロセスが読み書き可能 なディレクトリにします。このディレクトリは、 egg がコードの展開を必要とする 場合に使われます。

次に、 mod_python の PythonImport ディレクティブを使って、 mod_python が一 番最初にこのファイルを import するよう指定します。まず、前述の 「 ひとつの Apache で複数の Django を使う 」の節で説明した PythonInterpreter ディレクティブを設定しておきます (複数の Django をイ ンストールしない場合でも必要です)。 次に、メインのサーバ設定 (LocationVirtualHost セクションの外) に、以下のように PythonImport 行を追加します:

PythonInterpreter my_django
PythonImport /path/to/my/project/file.py my_django

mod_python マニュアル で定義されている通り、モジュールの指定は絶対パス (またはドット区切りの import パス表記) で行えます。ここでは絶対パスを使って いますが、これは、 PythonImport を処理する時点では、プロジェクトへの Python パスを変更する操作がまだ完了していないからです。

エラー処理

Apache/mod_python を使っている場合、エラーは Django によって捕捉されます。 別の言い方をすれば、 エラーは Apache レベルまで伝播せず、 Apache の error_log には出力されないということです。

例外は Django のセットアップが全くうまくいっていない場合で、この場合には "Internal Server Error" がブラウザに表示され、 error_log ファイルには完 全な Python のトレースバックが出力されます。 (error_log トレースバック は複数のログエントリ行に展開されます (これは見苦しくて読みづらいのですが、 mod_python のやり方なので仕方ありません)。

セグメンテーション違反になる場合

Apache がセグメンテーション違反 (segumentation fault) を引き起こす場合、 2 種類の原因が考えられます。いずれも Django 自体とは関係のない原因です。

  1. Python コードが "pyexpat" モジュールを import している場合。 "pyexpat" は Apache に埋め込まれているバージョンと衝突する場合があり ます。詳しくは、 Expat Causing Apache Crash を参照してください。
  2. mod_python と mod_php を同じ Apache のインスタンスで動作させ、バック エンドに MySQL を使っている場合。PHP と Python MySQL バックエンドと のバージョン衝突で引き起こされる既知の問題かもしれません。これについ ては mod_python FAQ entry に詳しく書かれています。

mod_python を使った設定で問題を解決できない場合、まずは Django フレームワー クなしの素の mod_python サイトを動かすようにしてみるとよいでしょう。そうす れば、mod_python 固有の問題を簡単に切り分けられます。この手順については Getting mod_python Working で詳しく説明しています。

次のステップでは、テストコードを編集して、自分が使っている全ての Django 関 係のコード -- ビュー、モデル、 URLconf, RSS の設定など -- を import してみ ます。これらのモジュールを import する文をテストハンドラ関数に入れ、ブラウ ザでテストハンドラの URL にアクセスしてください。クラッシュするようなら、 Django コードの import が問題の原因だということになります。クラッシュしなく なるまで段階的に import するモジュールを減らしてゆき、原因のモジュールを特 定してください。原因のモジュールを調べて、中で import しているモジュールを 必要に応じて調べて下さい。