.. _howto-deployment-modpython: ========================================= Apache と mod_python で Django を動かす ========================================= .. highlight:: apache :revision-up-to: 8961 (1.0) Django をプロダクションサーバ上で動かす設定として、現状では Apache_ と `mod_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 を動かす ` もどうぞ (SCGI と AJP もカバーしています)。 .. _Apache: http://httpd.apache.org/ .. _mod_python: http://www.modpython.org/ .. _mod_perl: http://perl.apache.org/ .. _prefork MPM: http://httpd.apache.org/docs/2.2/mod/prefork.html .. _worker MPM: http://httpd.apache.org/docs/2.2/mod/worker.html .. _Basic configuration: 基本的な設定 ============ Django を mod_python で動かすようにするには、まず Apache がインストールされ、 mod_python モジュールが有効になっていることを確かめます。 次に、 ``httpd.conf`` ファイルを編集し、以下のような設定を追加します:: SetHandler python-program PythonHandler django.core.handlers.modpython SetEnv DJANGO_SETTINGS_MODULE mysite.settings PythonOption django.root /mysite PythonDebug On ``mysite.settings`` は、 Django プロジェクトの設定ファイルを指す Python import パスになるよう、自分の環境に合わせて置き換えて下さい。 この設定は、 Apache に 「/mysite/ の下の全ての URL は mod_python で処理し、 処理には Django mod_python ハンドラを使うように」命令します。また、 :ref:`DJANGO_SETTINGS_MODULE ` を渡して、 mod_python にどこに設定ファイルがあるのか教えます。 .. versionadded:: 1.0 ``PythonOption django.root ...`` が新たに登場しました。 mod_python は、サイトを ``/mysite/`` プレフィクスの下で提供していることを自 動的に検出できないので、 ``PythonOption django.root ...`` を使ってハンドラ に通知してやる必要があります。この行に設定する値は、 ```` の引数と一致していなければなりません。 ``django.root`` を設定すると、 Django はリクエストの URL から ``django.root`` に設定されたプレフィクスを除 去した上で ``URLConf`` のパターンマッチングを行います。このため、後でサイト を ``/mysite2`` に動かした際に、 ``djnago.root`` だけを変更すればよくなりま す。 ``django.root`` を使う場合、必ず、プレフィクスを除去した後の URL がスラッシュ で開始するようにしてください。 そうでないと、先頭にスラッシュの入る URLConf の設定があった場合、パターンマッチングがうまくいきません。上の例では、 ``/mysite/admin/`` を ``/admin/`` に変えたいので、先頭から除去すべきなのは ``/mysite`` です。従って、 ``django.root`` の値を ``/mysite`` にしているの です。この場合、 ``/mysite/`` (末尾にスラッシュがついている) にしてしまうと、 エラーをひき起こすでしょう。 上の例では ```` ではなく ```` ディレクティブを使って います。前者はファイルシステム上の場所を指定するのに使い、後者はウェブサイ トのURL 構造上の場所を指定するのに使います。従って、 ```` を使っ た指定は意味をなさないのです。 また、 Django プロジェクトがデフォルトの ``PYTHONPATH`` 上になければ、以下 のような設定を mod_python に教えておく必要があります: .. parsed-literal:: 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"** PythonPath "['/path/to/project'] + sys.path" ``PythonPath`` には、アプリケーションから import したいモジュールの各々の 親ディレクトリを入れなければなりません。また、 :ref:`DJANGO_SETTINGS_MODULE ` の親ディレクトリも入れねばなりません。対話シェル を使う場合に Python パスを設定するのと同じです。何かモジュールを import す る際には、Python は必ず ``sys.path`` の各ディレクトリを順に調べ、その下から 該当モジュールを import しようと試み、 import に成功するまで探索を続けます。 分かりやすくするために例を挙げましょう。アプリケーションを ``/usr/local/django-apps/`` の下に配置しているとします (例えば、 ``/usr/local/django-apps/weblog/`` のようにです) 。そして、 ``mysite`` プロ ジェクトが ``/var/www/`` 下にあるとしましょう。上の例のように :ref:`DJANGO_SETTINGS_MODULE ` を設定している場合に は、 ``PythonPath`` を以下のように書かねばなりません:: PythonPath "['/usr/local/django-apps/', '/var/www'] + sys.path" これで、 ``import weblog`` や ``import mysite.settings`` が正しく動作します。 コード中で ``import blogroll`` していて、 ``blogroll`` が ``weblog/`` ディ レクトリの下にあるようなら、 ``/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`` を設定すべきであるということです。 ``PythonDebug`` が ``On`` に設定されたま まだと、 mod_python に不具合が生じたときに、恰好の悪い (そして赤裸々な) Python トレースバックを表示してしまいます。 Apache を再起動しましょう。 ``/mysite/`` やその下の URL へのリクエストが Django によって提供されているはずです。 Django の URLconf は ``/mysite/`` を切り取りらず、完全な URL を渡すことに注意して下さい。 Django で作られたサイトを mod_python 上で運営している場合、 Python コードに 対して変更を加える度に Apache を再起動する必要があります。 .. _Multiple Django installations on the same Apache: ひとつの Apache に複数の Django をインストールする ================================================== ひとつの Apache に複数の Django をインストールするのは簡単です。 ``VirtualHost`` を使って、以下のようにするだけです:: NameVirtualHost * ServerName www.example.com # ... SetEnv DJANGO_SETTINGS_MODULE mysite.settings ServerName www2.example.com # ... SetEnv DJANGO_SETTINGS_MODULE mysite.other_settings 一つの ``VirtualHost`` 設定の中に複数の Django をインストールしたい場合、 mod_python のキャッシュが Django の動作を台無しにしないように特に気を配る必 要があります。 ``PythonInterpreter`` ディレクティブを使って、 ```` ディレクティブごとに別のインタプリタを使うようにしてください:: ServerName www.example.com # ... SetEnv DJANGO_SETTINGS_MODULE mysite.settings PythonInterpreter mysite SetEnv DJANGO_SETTINGS_MODULE mysite.other_settings PythonInterpreter othersite ``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 のようにするか、ページのテンプレートにデバッグ情報を追加してください。 .. _mod_python のドキュメント: http://www.python.jp/doc/contrib/modpython/directives.html .. _mod_python documentation: http://modpython.org/live/current/doc-html/directives.html .. _serving-media-files: .. _Serving media files: メディアファイルの提供 ======================== Django は、自分ではメディアファイルの提供を行わず、ユーザの選んだ Web サー バにその仕事を任せます。 メディアの提供には、別のウェブサーバ、すなわち Django を動かしていないサー バを使うよう勧めます。お勧めはいくつかあります: * lighttpd_ * TUX_ * Apache_ の軽量化 (stripped-down) 版 とはいえ、Django を動作させているのと同じ Apache の ``VirtualHost`` でメディ アファイルを提供せざるを得ない場合には、以下のようにして特定の場所でだけ mod_python を切ります:: SetHandler None ``Location`` ディレクティブの引数を、メディアファイルを置いている場所のルー ト URL に置き換えて下さい。 ```` を使って、正規表現に一致さ せるようにもできます。 以下の例では、 Django をサイトのルートで設定し、 ``media`` サブディレクトリ の下と、 ``.jpg`` 、 ``.gif`` 、および ``.png`` で終わる URL だけでは明示的 に Django を無効にしています:: SetHandler python-program PythonHandler django.core.handlers.modpython SetEnv DJANGO_SETTINGS_MODULE mysite.settings SetHandler None SetHandler None .. _lighttpd: http://www.lighttpd.net/ .. _TUX: http://en.wikipedia.org/wiki/TUX_web_server .. _Apache: http://httpd.apache.org/ .. _howto-deployment-modpython-serving-the-admin-files: .. _serving-the-admin-files: .. _Serving the admin files: admin ファイルの提供 ==================== Django の開発サーバは自動的に admin メディアファイルを提供しますが、それ以 外の設定ではこれはあてはまりません。admin ファイルを提供するには、 Apache なりその他のメディアサーバなりで設定を行う必要があります。 admin ファイルは Django 配布物の (:file:`django/contrib/admin/media`) ディ レクトリ下にあります。 お勧めのアプローチは二つあります: 1. ドキュメントルートから admin メディアファイルへのシンボリックリンク を作ります。そうすれば、リンクを張った Django 関係のファイル (コード **と** テンプレート) を一箇所にまとめられるので、自分のコードを ``svn update`` するだけで admin テンプレートを最新の状態に保てます。 2. または、 admin メディアファイルをコピーして Apache のドキュメントルー トに入れます。 .. Using eggs with mod_python mod_python 上で "egg" パッケージを使う ======================================= Django を Python egg_ でインストールしたり、 Django から egg 化されたモジュー ルを使っている場合、いくつか追加の設定が必要です。プロジェクト中 (か、どこ か import できる場所) にファイルを作り、以下の内容を入れておきます: .. code-block:: python import os os.environ['PYTHON_EGG_CACHE'] = '/some/directory' ``/some/directory`` は Apache httpd を動作させているプロセスが読み書き可能 なディレクトリにします。このディレクトリは、 egg がコードの展開を必要とする 場合に使われます。 次に、 mod_python の PythonImport_ ディレクティブを使って、 mod_python が一 番最初にこのファイルを import するよう指定します。まず、前述の 「 `ひとつの Apache で複数の Django を使う`_ 」の節で説明した ``PythonInterpreter`` ディレクティブを設定しておきます (複数の Django をイ ンストールしない場合でも必要です)。 次に、メインのサーバ設定 (``Location`` や ``VirtualHost`` セクションの外) に、以下のように ``PythonImport`` 行を追加します:: PythonInterpreter my_django PythonImport /path/to/my/project/file.py my_django `mod_python マニュアル`_ で定義されている通り、モジュールの指定は絶対パス (またはドット区切りの import パス表記) で行えます。ここでは絶対パスを使って いますが、これは、 ``PythonImport`` を処理する時点では、プロジェクトへの Python パスを変更する操作がまだ完了していないからです。 .. _Egg: http://peak.telecommunity.com/DevCenter/PythonEggs .. PythonImport: http://www.modpython.org/live/current/doc-html/dir-other-pimp.html .. _PythonImport: http://www.python.jp/doc/contrib/modpython/dir-other-pimp.html .. _mod_python manual: PythonImport_ .. _`mod_python マニュアル`: `mod_python manual`_ .. _`ひとつの Apache で複数の Django を使う`: `Multiple Django installations on the same Apache`_ .. _Error handling: エラー処理 ========== Apache/mod_python を使っている場合、エラーは Django によって捕捉されます。 別の言い方をすれば、 エラーは Apache レベルまで伝播せず、 Apache の ``error_log`` には出力されないということです。 例外は Django のセットアップが全くうまくいっていない場合で、この場合には "Internal Server Error" がブラウザに表示され、 ``error_log`` ファイルには完 全な Python のトレースバックが出力されます。 (``error_log`` トレースバック は複数のログエントリ行に展開されます (これは見苦しくて読みづらいのですが、 mod_python のやり方なので仕方ありません)。 .. _If you get a segmentation fault: セグメンテーション違反になる場合 ================================ 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 しているモジュールを 必要に応じて調べて下さい。 .. _Expat Causing Apache Crash: http://www.dscpl.com.au/articles/modpython-006.html .. _mod_python FAQ entry: http://modpython.org/FAQ/faqw.py?req=show&file=faq02.013.htp .. _Getting mod_python Working: http://www.dscpl.com.au/articles/modpython-001.html