trac と Django アプリケーションをapache+mod_pythonで

社内向けDjangoアプリを公開するためにapacheをセットアップして、ついでに課題管理用にtracをセットアップしてみた。
そしたら半日くらいはまったのでメモしておく。
環境は apache 2.0.59, mod_python 3.3.1, python 2.4, Django 0.96, trac 0.10.3.1-ja

理想としては http://www.djangoproject.com/ みたく、

  • www.servername -> Django アプリ
  • trac.servername -> trac サイト

としたかったんだけど、ネットワークの知識がないので断念した。


しかたないので、

  • servername -> Django アプリ
  • servername/trac -> trac サイト

という風にしようとhttpd.confをこう書いたら、tracサイトにアクセスできない。
/trac以下もDjangoにハンドルされているようだ。

<Location />
    PythonPath "['d:/django'] + sys.path"
    SetHandler python-program
    PythonHandler django.core.handlers.modpython
    SetEnv DJANGO_SETTINGS_MODULE djangoproject.settings
    PythonDebug off
</Location>
<Location /trac>
    SetHandler mod_python
    PythonHandler trac.web.modpython_frontend
    PythonOption TracEnv d:/trac/tracproject
</Location>


それなら、といことで安易に

  • servername/django -> Django アプリ
  • servername/trac -> trac サイト

としようとしたら、tracサイトは見れるけどDjangoアプリは404だらけでまともにアクセスできなくなった。
URLマッパーが/djangoを切り取らないからっぽい。
というかlogin_requiredデコレータが/account/loginにリダイレクトするので困った。


いろいろ試行錯誤していたら、上記の設定をVirtualHostで囲んだら動いた。理由はよく分からない。
ついでにSubversionWebDAVも設定してみる。
結果としてこんな構成になった。

物理的な構成はこんなかんじ。

  • d:/django/djangoproject -> Djangoプロジェクト
  • d:/www/media -> Djangoの管理画面用メディアファイル
  • d:/www/site_media -> Djangoプロジェクト用メディアファイル
  • d:/trac/tracproject-> tracプロジェクト
  • d:/svn/repo-> Subversionリポジトリ

tracプロジェクトとSubversionリポジトリのアカウントは共通化した。
本当はDjangoの認証を利用したかったけど、うまくいかなかった。


httpd.confはこんなかんじ

DocumentRoot "d:/www"

LoadModule dav_module modules/mod_dav.so
LoadModule dav_fs_module modules/mod_dav_fs.so
LoadModule python_module modules/mod_python.so
LoadModule dav_svn_module "C:/Program Files/Subversion/bin/mod_dav_svn.so"
LoadModule authz_svn_module "C:/Program Files/Subversion/bin/mod_authz_svn.so"

<VirtualHost *>
#for Django
    <Location />
        PythonPath "['d:/django'] + sys.path"
        SetHandler python-program
        PythonHandler django.core.handlers.modpython
        SetEnv DJANGO_SETTINGS_MODULE djangoproject.settings
        PythonDebug off
    </Location>
    <Location /media>
        SetHandler None
    </Location>
    <Location /site_media>
        SetHandler None
    </Location>
#for trac
    <Location /trac>
        SetHandler mod_python
        PythonHandler trac.web.modpython_frontend
        PythonOption TracEnv d:/trac/tracproject
    </Location>
    <Location /trac/login>
        AuthType basic
        AuthName "Trac"
        Require valid-user
        AuthUserFile d:/trac/tracproject/.htpasswd
    </Location>
</VirtualHost>

#for Subversion
<location /svn>
    DAV svn
    SVNPath d:/svn/repo
    AuthType basic
    AuthName "Subversion"
    Require valid-user
    AuthUserFile d:/trac/tracproject/.htpasswd
</Location>

trac サイトにスパム対策

以下のエントリの続き。


インタアクトさんから trac-0.10-ja-1 が出てたので、さくらに構築した trac サイトを更新しようとしたら、またもやスパムにやられていたのに気付いた。しかも結構大量に。
前回の方法だとさすがに面倒なので、プラグインがないか探してみたらあっさり見つかった。-> TicketDeletePlugin


削除はプラグインで簡単になったけど、それでも繰り返すのは面倒なので SpamFilterPlugin も入れてみた。

TicketDeletePlugin

http://trac-hacks.org/wiki/TicketDeletePlugin
インストールはいつもの通り python setup.py install --home=$HOME/local
TicketDeletePlugin を有効にすると Admin メニューに「Delete Changes」、「Delete」というサブメニューが表示される。

チケットの変更点の削除

「Delete Changes」を選択すると、チケット番号の入力を求められる。

入力すると選択したチケットの変更点一覧が出てくるので、削除したい変更点を選んで「Delete Checked」ボタンをクリックする。

チケットの削除

「Delete」を選択すると、チケット番号の入力を求められるので、チケット番号を入力してやればいい。

SpamFilterPlugin

http://trac.edgewall.org/wiki/SpamFilter
これもインストールはいつもの通り python setup.py install --home=$HOME/local

WordPress API key の入手

SpamFilterPlugin は Akismet というWebサービス?を利用しているらしい。これには WordPress API key が必要なんだけど、WordPress に登録すれば簡単に手に入るので省略。
入手した WordPress API key を使って 、trac.ini に以下の設定を追加

[akismet]
api_key = 1234567890


さてちゃんと防げるかな?

TracBlogPlugin が表示できなくなった時の復旧方法

trac をプロジェクトのポータルサイトとして使うために の続き。
上記の環境ではプロジェクトメンバーとの情報共有に TracBlogPlugin を使っている。
WikiStart からもエントリを投稿できるようにしているわけだが、ある時間違えて空のエントリを投稿してしまった。
そうすると下記のようなエラーが出て、以降ブログ記事が表示できなくなった。

Traceback (most recent call last):
  File "c:\python24\Lib\site-packages\trac\web\main.py", line 356, in dispatch_request
    dispatcher.dispatch(req)
  File "c:\python24\Lib\site-packages\trac\web\main.py", line 224, in dispatch
    resp = chosen_handler.process_request(req)
  File "build\bdist.win32\egg\tBlog\web_ui.py", line 216, in process_request
  File "build\bdist.win32\egg\tBlog\web_ui.py", line 267, in _generate_blog
StopIteration

WikiStart の表示もこのとおり。

復旧手順

Wiki のデータがおかしいのだろうと思い、trac-admin で Wiki list とやってみたが、該当するデータはなかった。
その時点で途方に暮れたわけだが、さっき思いついた方法で無事復旧できた。
何のことはない、Wiki ではなくてタグが悪さをしていたらしい。
手順としては、
1. sqlitetrac.db を開く。
2. SELECT * FROM tags; で最新のタグを探す。2006/10/20 23:12 に投稿したエントリは以下のように記録されているはず。

wiki|2006/10/20/23.12|blog
wiki|2006/10/20/23.12|news

3. DELETE FROM tags WHERE name = '2006/10/20/23.12'; で該当するエントリのタグを削除する。

さくらレンタルサーバに構築した trac サイトのコメントスパムを削除する

trac サイトを構築した時のメモ の続き。
以前構築した 別館 のチケットにコメントスパムが投稿されているのに気付いた。本人ですらたまにしか見ないのに。恐るべしスパマー。

今のところ trac にチケットのコメントを削除する方法は用意されていないが、見た目に宜しくないのでsqlite を使って削除した。
そのときの手順をメモしておく。

sqlite

とりあえず sqlite をインストールしないと話にならないのでインストール。

%wget http://sqlite.org/sqlite-3.3.7.tar.gz
%tar xzvf sqlite-3.3.7.tar.gz
%cd sqlite-3.3.7
%./configure --prefix=$HOME/local
%make
%make install

trac.db を修正

http://trac.edgewall.org/ticket/454 を参考にSQLを投げるだけ。
まずはさくらに接続して、$repo/db/trac.db を開く。

sqlite3 trac.db

すると sqlite3 がコマンドを待つので、

SELECT * FROM ticket_change WHERE ticket=3

と入力する。(最後の数字は[修正したいチケット番号]に変更する)
すると以下のようにチケットの修正一覧が表示される。

3|1154847902|goodspeed|status|new|closed
3|1158265726|Brendan|comment||Some links for you・・・

この中からスパムによって修正されたレコードを探して、そのレコードの2列目の数字(この場合は[1158265726])を使ってDELETE文を投げる。

DELETE FROM ticket_change WHERE ticket=3 and time=1158265726

sqlite は .quit で終了する。

trac をプロジェクトのポータルサイトとして使うために

trac は標準でもかなり高機能なんだけど、使っているうちにそれなりに不満点は出てくる。
個人的に、標準では使いにくいと思うものがいくつかあって、今のところこれくらい。

  1. ユーザ管理
    -> 標準だとコマンドラインで trac-admin するしかない。
    -> サーバまで移動する or リモートログイン。面倒。
  2. ニュースの表示
    -> 一番目立つ WikiStart を編集するとか?
    -> ニュースであることが気付き難いし、過去のニュースが追えない。
  • 関連する情報へのリンク
    ->手動で関連情報にリンク。
    -> めんどくさいし、漏れが出るのは確実だろう。

あとは議論するための仕組み(-> DiscussionPlugin ?)とか、自分のタスク一覧確認(-> デフォルトのレポート7?)が必要かとも思うけど、標準でもなんとかなるように思う。

trac の場合、プラグインやマクロを使えばある程度はカバーできて、自分もそうしている。
今までインストール方法はいくつかメモしたけど、ポータルサイトとして使うためにどこまで拡張するか書いてなかったのでメモしておく。
前提とする環境は trac 0.10 beta1 on Windows + Python 2.4 の環境。

ユーザ管理

ブラウザ上からユーザ管理を可能にするために、以下の3つのプラグインを使う。

WebAdminPlugin 0.1.1 dev-r2765

前提とする環境ではインストール済み。

AccountManagerPlugin 0.1.2

コマンドラインから easy_install を叩けばいい。
http://trac-hacks.org/svn/accountmanagerplugin/trunk だと失敗した。

c:\python24\scripts\easy_install http://trac-hacks.org/svn/accountmanagerplugin/0.9

trac.ini に以下の設定を追加する。

[account-manager]
password_format = htpasswd
password_store = HtPasswdStore #0.10系だと必要らしい。
password_file = c:/repos/trac/.htpasswd
WebAdminUsersPlugin 0.1.0

ダウンロードしたzipを展開して、setup.py の3行目、4行目をコメントアウトした状態で setup.py を叩けばいい。

#setup.py のコメントアウト
#import ez_setup
#ez_setup.use_setuptools()
python setup.py install


上記3つのプラグインを有効にすると admin メニューに「User Accounts」というサブメニューが出来て、ユーザ管理が出来るようになる。

2006/09/20 追記
アカウントに直接権限を与えるのではなくて、developerとかmanagerとかグループを作成する。グループに権限を与えて、そのグループにアカウントを所属させるようにすると楽。

ニュース表示

Trac Hacksっぽくニュースを表示するために、以下の3つのプラグインを使う。

TagsPlugin 0.4

TracTags-0.4-py2.4.egg をダウンロードして、easy_install。

c:\python24\scripts\easy_install TracTags-0.4-py2.4.egg
TracBlogPlugin 0.2.1 dev

ダウンロードしたzipを展開して、0.10フォルダにある setup.py を叩けばいい。

python setup.py install
NewsFlashMacro 0.1 (マクロと言いながらプラグイン?)

ダウンロードしたzipを展開して、0.9フォルダにある setup.py を叩けばいい。

python setup.py install


次に trac.ini を以下のように編集する。

[components]
trac.wiki.web_ui.wikimodule = disabled # 追加
[trac]
default_handler = TagsWikiModule # WikiModule から変更


最後に上記3つのプラグインを有効にした状態で trac プロジェクトをアップグレードする。

python c:\python24\scripts\trac-admin c:\repos\trac\projectname upgrade


この状態で WikiStart 等に以下のように記述するとニュースが表示されるようになる。
(もちろんニュースを投稿している状態で)

2006/09/20 追記
1つ利点に気付いた。blog機能をニュース投稿のみに使って、そのRSSフィードRSSリーダに登録するようにすれば、プロジェクトのMLにメールを流す必要がなくなる。ある程度の規模のプロジェクトならこの効果は大きいと思う。
[[NewsFlashStart]]
[[BlogPost(tag=(blog,news),readonly=1)]]
[[BlogShow(news,num_posts=3,hidecal=true)]]
----
過去のニュースは[/projectname/blog こちら]
[[NewsFlashEnd]]

関連する情報へのリンク

以下のマクロを使う。

BackLinksMacro

ダウンロードした BackLinks.py を c:\repos\trac\projectname\wiki-macros にコピーする。
あとはリンクを張りたいwikiページに以下のようにマクロを記述すればいい。

[[BackLinks(TargetWikiPage)]]

チケットにも同じような仕組みがあると助かるけど、今のところ見つからない。
これに関してはもう一工夫必要かと思う。

2006/09/20 追記
不具合?を見つけた。WikiPageNameにマッチしない単語でページを作ると、リンクしてなくてもその単語が含まれていれば一覧に表示されてしまう。

あると便利なもの

あとは必要に応じてマクロを追加するくらい。といっても使うのはこれくらいかな。

2006/09/20 追記
脚注に日本語が使えなくなっていた。結構致命的で、作者もアイデアが思いうかばないっぽい。

trac 0.10 beta1 on Windows + Python 2.4

の続き。beta1 は様子見かな、と思ってたら Subversion 1.4.0 のReleaseNote に svn-python-1.4.0-py2.4.exe を見つけた。
そこで Python 2.4 で動くかどうか試してみたら動いたのでメモしておく。

インストールリスト

インストールするものは以前とほとんど同じて、Python 2.4 用のものを使う。
インストーラは全部デフォルトインストールしていけばいい。

trac プロジェクトの作成

initenv コマンドでプロジェクトを作成する。ついでにユーザに管理権限を与えておく。

python C:\Python24\scripts\trac-admin c:\repos\trac\projectname initenv
#以下は都度入力する
Project Name [My Project]> projectname
Database connection string [sqlite:db/trac.db]> #そのままENTERでいい
Repository type [svn]> #そのままENTERでいい
Path to repository [/path/to/repos]> c:/repos/svn  #svnリポジトリへのパス
Template directory [c:\python24\share\trac\templates]> #そのままENTERでいい
#ここからユーザ権限の追加
python C:\Python24\scripts\trac-admin c:\repos\trac\projectname permission add username TRAC_ADMIN
2006/09/16 追記
リポジトリブラウザで日本語を使うため、trac.ini の trac セクションで default_charset = cp932 と修正する。
Python2.3 + JapaneseCodec では default_charset = japanese.shift_jis としていたが、Python2.4ではエラーが発生する。

WebAdmin プラグイン

http://projects.edgewall.com/trac/wiki/TracPlugins から ez_setup.py をダウンロードして c:\repos\trac に置いておく。以下のコマンドを実行すると c:/python24/scripts にeasy_install.exe がダウンロードされる。今後はこれを使ってプラグインを入れるらしい。

python c:\repos\trac\ez_setup.py

http://projects.edgewall.com/trac/wiki/WebAdmin から TracWebAdmin-0.1.1dev_r2765-py2.4.egg をダウンロードしてコマンド実行。

c:/python24/scripts/easy_install TracWebAdmin-0.1.1dev_r2765-py2.4.egg

trac.ini に以下の設定を追加。

[components]
webadmin.* = enabled

apache の設定変更

httpd.conf に設定を追加。dav_module と dav_fs_module は既存行のコメントアウトを外しても構わない。
※ c:/trac/.htpasswd を用意しておくこと。

#TRAC with mod_python
LoadModule dav_module modules/mod_dav.so
LoadModule dav_fs_module modules/mod_dav_fs.so
LoadModule python_module modules/mod_python.so
LoadModule dav_svn_module "C:/Program Files/Subversion/bin/mod_dav_svn.so"
LoadModule authz_svn_module "C:/Program Files/Subversion/bin/mod_authz_svn.so"
<VirtualHost *:80>
  <LocationMatch "/[[:alnum:]]+">
    SetHandler mod_python
    PythonHandler trac.web.modpython_frontend
    PythonOption TracUriRoot /
    PythonOption TracEnvParentDir c:/Repos/trac
  </LocationMatch>
  <LocationMatch "/[[:alnum:]]+/login">
    AuthType Basic
    AuthName "trac"
    AuthUserFile c:/Repos/trac/.htpasswd
    Require valid-user
  </LocationMatch>
</VirtualHost>


以上で http://locahost/projectnametrac にアクセスできるようになる。
まだインストールしただけなので違いがよく分からないが、リポジトリブラウザからZIPでダウンロードできるようになったのが地味にうれしい。

wiki を PDF に変換するプラグインを入れたけど変換できない

trac を使う上で最大の障害になるのは、納品ドキュメントをどうするかってことじゃないかと思う。


職場でよく見かけるのは、 EXCEL で仕様書を書いて変更履歴シートに変更内容を数行で書いていくもの。それを VSS でバージョン管理するわけだけど、はっきり言ってどこがどう変更されたのかさっぱり分からん。trac なら diff がすぐに取れるのに・・・と思う。


そこで仕様書も trac で! とやりたいけど、そうなると納品するときが問題だ。
アプローチとしては

  • trac で仕様書を書き、HTMLを印刷。
    → 発注先が納得しないだろうなあ・・・
  • 基本的に trac で仕様書を書き、あるタイミングで EXCEL などに手動で移す。
    → 多分受け入られない。最終的に EXCEL になるんなら最初から EXCEL で書くほうが工数がかからない、という理由で。

とりあえずHTML印刷は無理だろう。かといって EXCEL への手動コンバートも無理っぽい。じゃあ自動コンバートする仕組みがあればいいのでは?と思い探していたらPDFに変換するプラグイン PageToPdfPlugin を見つけた。


これはいい、と思ってインストールしてみたんだけど、PDFが生成されない。Trac Hacks では生成できているので何かが足りないようだ。とりあえず手順をメモしておく。

trac 0.10dev のアップグレード

trac は r3305 からコンバートAPIができたらしい。PageToPdfPlugin はこのAPIを使っているわけだけど、r3305 では PageToPdfPlugin が動かなかったので、http://svn.edgewall.com/repos/trac/trunk から最新の r3462 をチェックアウトしてアップグレードした。

PageToPdfPlugin のインストール

http://trac-hacks.org/wiki/PageToPdfPlugin から pagetopdfplugin-r942.zip をダウンロード。解凍してできた setup.py を叩いて、trac.ini に以下の設定を追加する。

[components]
pagetopdf.pagetopdf.pagetopdfplugin = enabled

htmldoc のインストール

実際にPDFに変換しているのは HTMLDOC らしい。
http://www.easysw.com/htmldoc/software.php からインストーラをダウンロードできるけど、ライセンスを買わないとだめっぽい。とりあえず試用のライセンスを取ってパスを通してみた。


これでとりあえず PDF のリンクが出てくるようになって、ファイルのダウンロードもできる。が、ファイルサイズが 0KB になってしまう。原因は不明。
Trac Hacks の変換結果を見る限り、CSSとかは反映されないみたいなので、これ以上は追及しないつもり。バージョンアップしたら追いかけよう。