DjangoのWSGIを使ってレスポンスを取得してみる

今回はDjangoで作った自分のサイトhttp://tokibito.orz.hm/をちょっとサーバー動作なしで動かしてみようかと思った。
E:\WebSitesにdjango-admin.pyで作ったプロジェクトフォルダが置かれてる状態。(ソースはSVNで管理してます)

とりあえずWindowsなのでコマンドだとUTF-8が文字化けしちゃうから、

E:\WebSites>chcp 65001

としておいた。このコマンドを実行する前に、コンソールのプロパティでフォントをMSゴシックにしとかないと日本語文字化けするんで注意。
python起動

E:\WebSites>python
Python 2.5 (r25:51908, Sep 19 2006, 09:52:17) [MSC v.1310 32 bit (Intel)] on win 32
Type "help", "copyright", "credits" or "license" for more information.
>>> import os, sys
>>> os.environ['DJANGO_SETTINGS_MODULE'] = 'tkhp.settings'
>>> import django.core.handlers.wsgi
>>> application = django.core.handlers.wsgi.WSGIHandler()
>>> application.load_middleware()
>>> from django.http import HttpRequest
>>> req = HttpRequest()
>>> req.path = '/'
>>> res = application.get_response(req)
>>> print res
Content-Type: text/html; charset=utf-8

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/
DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
<head>
  <title>tokibito's software</title>
</head>
<body>
  <div class="banner">
    <img src="/static/image/tkhp_banner_200x40.jpg" width="200" height="40" alt=
"tokibito's software" />
  </div>
  <p>
    準備中です。<br />
    Ubuntu7.04 Apache2+mod_wsgiでDjango0.96(Python2.5)稼動中。<br />
    相変わらずDBはSQLite3使ってる。<br />
  </p>
</body>Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IOError: [Errno 0] Error

IOErrorが出たのは何故だろう。もしかして表示できない文字でも含んでたのか。
ところでこの出力をDelphi+P4DでTWebBrowserに書き込めばブラウザで見れるよねって話。そういやIEコンポーネントでレスポンスをハックってどうやったらできるんだろか。画像とかのレンダリング方法を考えないと。

  • 追記

res.contentをファイルに出力したらエラーは出なかった。

PythonのアップグレードとPython for Delphiのインストールなど

サーバがPython2.5なのに、開発環境がPython2.3JPなのはさすがにまずいだろうと思ってPythonをアップグレードすることにしました。
アップグレードといっても特に難しいことはなく、古いのを消して新しく入れなおしただけなんですけどね。ついでに前々から試そうと思っていたPython for Delphi(P4D)も入れてみました。

  • 今回インストールしたもの


Python 2.5, pysqlite 2.3.4(Python 2.5, Win32), Django 0.96, Python for Delphi 3.3.2

  • Pythonのアンインストールとインストール

[プログラムの追加と削除]よりPython2.3のアンインストールを行い、"python-2.5.msi"を実行して特に設定を変更することなく"C:\Python25"にインストール。[マイコンピュータ]-[詳細設定]-[環境変数]で"Path"の値に"C:\Python25"と"C:\Python25\Scripts"を追加しました。

  • pysqliteのインストール

これも"pysqlite-2.3.4.win32-py2.5.exe"を実行して設定を変更することなくインストールしました。

アーカイブを展開して、コマンドプロンプトから"python setup.py install"を実行してインストールしました。

これが予想外に簡単だった。Delphi2005をインストール済みの環境だが、"P4D.exe"を実行してインストーラDelphiのバージョンを自動検出してくれた。

以上、特に問題もなくインストール終了。

追記

Python2.5だと最初からsqlite3モジュールが入っているのでpysqlite2を入れなくても大丈夫だったかな。

DjangoとAjaxでハードディスクの容量を表示

少しずつ時間をとって最近作ってたのがこれ。Pythonでpipeを使って実行したdfコマンドの結果を整形し、Djangoでviewを作ってAjaxで表示したもの。Ajaxのライブラリには、SimpleJSを使ってみた。

ファイルの命名は適当ですがお気になさらず。サイズを取得してるディレクトリとかは、それぞれの環境に読み替えよろしく。Djangoについて多くは書かないので参考程度に。Windowsでは当然動きませんがあしからず。

  • projectdir/modules/status.py
import os
import re
def diskinfo(dir):
    pipe = os.popen('df -h | grep \" %s$\"' % dir, 'r')
    text = pipe.read()
    pipe.close()
    info = re.split('[\s]+',text)
    if text != '':
        return {'volume':info[0], 'total':info[1], 'used':info[2], 'free':info[3], 'useper':info[4]}
    else:
        return None
  • projectdir/diskinfo/views.py
from projectdir.modules import status
from django.http import HttpResponse

def diskinfo_ajax(request, dir, prop):
    if dir == '_extra1':
        d = '/var/ftp/_extra1'
    elif dir == 'global':
        d = '/'
    else:
        d = '/'
    st = status.diskinfo(d)
    return HttpResponse(st[prop])
  • projectdir/diskinfo/urls.py
from django.conf.urls.defaults import *
from django.conf import settings

urlpatterns = patterns('',
    (r'^ajax/(?P<dir>\w+)/(?P<prop>\w+)/$', 'projectdir.diskinfo.views.diskinfo_ajax'),
)
  • projectdir/static/js/diskinfoajax.js
function LoadDiskInfo() {
  $ajaxreplace("diskused_global", "/diskinfo/ajax/global/used/", false);
  $ajaxreplace("disktotal_global", "/diskinfo/ajax/global/total/", false);
  $ajaxreplace("diskused_extra1", "/diskinfo/ajax/_extra1/used/", false);
  $ajaxreplace("disktotal_extra1", "/diskinfo/ajax/_extra1/total/", false);
}
  • /projectdir/templates/index.htm
{中略}

<script language="JavaScript" type="text/javascript" src="/static/js/simple.js"></script>
<script language="JavaScript" type="text/javascript" src="/static/js/simpleajax.js"></script>
<script language="JavaScript" type="text/javascript" src="/static/js/diskinfoajax.js"></script>

{中略}

<body onload="LoadDiskInfo();setInterval(LoadDiskInfo, 30000);">

<table class="diskinfo_table">
  <tr>
    <td>/</td><td class="disksize"><span id="diskused_global">----</span>/<span id="disktotal_global">----</span></td>
  </tr>
  <tr>
    <td>/_extra1/</td><td class="disksize"><span id="diskused_extra1">----</span>/<span id="disktotal_extra1">----</span></td>
  </tr>
</table>

{中略}

30秒間隔で自動更新。

settings.pyでBASE_DIRを定義する

Djangoのアプリケーションをローカルでrunserverで動かす場合は、相対パスでテンプレートディレクトリ等を指定しても問題ないのだが、Apache経由等で動作させたりすると、カレントディレクトリの関係上うまくいかないことが多い。
settings.pyでBASE_DIRを定義するのがスマートなようだ。

  • settings.pyの最初のほうに以下を追加
import os
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
  • SQLiteのDBファイルの設定例
DATABASE_NAME = os.path.join(BASE_DIR, 'data/dbfile')

各アプリケーションフォルダの下にあるtemplatesフォルダは特に設定なしでも認識されているが、プロジェクトフォルダ直下に作った場合は認識されなかった。テンプレートを一つのフォルダにまとめたかったので、TEMPLATE_DIRSの設定を行った。

TEMPLATE_DIRS = (
    os.path.join(BASE_DIR, 'templates'),
)

settings.pyを普通にimportすれば他のソースファイルでも使えるので、何かと便利。

from django.conf import settings

ちなみにDjangoのバージョンは0.96です。