A very minimal Product
やっと
いまさらながら
http://www.zope.org/Members/maxm/HowTo/minimal_01
を見ながらやってみる。
実際読むだけでなく自分でやっていくと結構勉強になる。
Hello World
http://nakaj.net/minimalproduct/test
Count 1 to 10
http://nakaj.net/minimalproduct/test/counter
べき乗
http://nakaj.net/minimalproduct/test/squareForm
Zope技術入門のプロダクトの例は最初から高度すぎて読んでもぴんとこなかったが
この例題は読んでて「あ、なるほどね」と思えた。ま、私の程度が低い訳ですが。
ちと恥ずかしい。
最初はコメントが面倒だったので
def xxxx():
""
return """<html>
....
</html>"""
とかしてたら"empty or missing docstring"なんて怒られた^^;。
省略不可なんだ、zopeだと。
その他にもいろいろ気づかされたけど、あまりにも基本的なことばかり
みたいなので恥ずかしいので書きません。
あ、こんなにいい例題があったなんて私は今日知りました、、、、。
#コメントというよりドキュメンテーション文字列と呼ぶのかな、
ZKInterbasdbDA-0.3.0
早速使わせてもらってます
テストのDBをまず作りました。
まず以下のようなテーブルを作る
CREATE TABLE "TB1"
( "PID" INTEGER, "F1" INTEGER, "F2" INTEGER);
プロシジャーを作ります。
二つの値を受け取りTB1テーブルにインサートし、最新のインサートされた値を返す、あまり意味はないプロシジャーですが。
Windowsのコマンドラインからの isqlでも以下のようにset termすればprocedureを作成できると思います。>中神さま
SET TERM ^ ;
/* PROCEDURE内で ; を利用するためSET TERMで ^ に変更します */
CREATE PROCEDURE "P_INS_TB1"
( "V1" INTEGER, "V2" INTEGER)
RETURNS
( "R1" INTEGER, "R2" INTEGER)
AS
begin
insert into tb1(f1,f2) values(:v1, :v2);
select f1, f2 from tb1 where pid = (select max(pid) from tb1)
into :r1, :r2;
suspend;
end
^
SET TERM ; ^
COMMIT WORK;
ユニークキーを作るためのジェネレータをつくります。
CREATE GENERATOR "GEN_PID";
上記generatorを利用するためのトリガーを作ります。
CREATE TRIGGER "TRG_PID" FOR "TB1"
ACTIVE BEFORE INSERT POSITION 0
as
begin
new.pid = gen_id(gen_pid,1) ;
end
^
COMMIT WORK ^
SET TERM ;^
そして値をいれてみて動作を確認しました。
IB,Firebirdではselect文でprocedureを利用できるというユニークですがわかりやすい機能があります。
SQL> select * from p_ins_tb1(1,2);
R1 R2
============ ============
1 2
SQL> select * from p_ins_tb1(3,4);
R1 R2
============ ============
3 4
SQL> select * from tb1;
PID F1 F2
============ ============ ============
1 1 2
2 3 4
というような感じになります。プロシジャー文内でコミットしていないのでデータの信憑性はないわけですがテストケースとして作ったのでご容赦。
さてこうして作ったデータベースをbrowseタグでみてみますとgenerator, procedureは無事表示できました。
非常に便利です。
ただtriggerだけが表示されませんでした。
ところがexamplesのなかのemployee.fdbに関してはtableのツリー以下で表示できています。
(FireBirdインストール時につくられるサンプルDB)
キャプチャしました
それとZopeを再起動したときにDAのコネクションがcloseされてしまうようです。
ただこれはもしかすると私の勘違いかもしれません。そうたびたび再起動するわけにいかない場所で作ってしまったため、ぜひどなたかテストしていただけないでしょうか?
super serverの場合サーバのリスタートは
/etc/init.d/xinted restart
わからなくっててんてこ舞いでした。
トリガー、引き金に見えますかね、、、、。
trigger_inactive.gif
trigger.gif
ZKInterbasdbDA-0.3.4リリースです
中神さん有難うございます
テスターが私だったばっかりにレアな環境に対応させてしまいました。お詫び申し上げます。
>中神さん
ということで
ZKInterbasdbDA-0.3.4のご紹介です。
なんといってもこのBrowseタグ。DBスキーマをここまで表示してくれています。
今まで私が使ったDAのなかではプライマリキー、外部キー、プロシジャー、トリガー、ジェネレータ、ビュー、、、まで表示してくれたものはなかったと思います。
これをみたらぽすぐれやマイえすくーるをZopeでお使いの方も使いたくなるのではーー。
IBやFBをBorland製品からお使いでWebアプリに興味お持ちの方にもどうでしょう?
使い方はこちら(中神さんのページ)
#キャプチャはちょー適当なDBなので気になることがあっても気にしないでくださいませ^^;
#browseタグを押したとき、クエリーが発行されたときにStatusがOpenになるようにしたのはSQLコネクションが切れているとき(DBMSが起動してないなどで)そのDAがあるフォルダを覗くとやたら時間がかかってしまう、という奴の対策の一つなんだろうか?
結構これに私は苦しめられまして、以前。だから安心して使ってます。
OpenSharePointだそうです
気になる気になる
http://opensharepoint.sourceforge.net/
デモのリンク先などを見るとタイ語が使われていたり、日本語ファイルを投稿している人がいたりする。
UTF-8にブラウザを設定したら日本語ファイルが読めたからマルチバイト対応はできているよう。
ただ、リロードや移動するとisoに戻されて化けてしまうからそのあたりはトランスレータの仕事なんでしょう。
sourceforgeをみてるとドキュメントがまだまだだからインストールから苦労することは目に見えてるなぁ。
でも試してみたい。
で、だれか日本語化しませんかね?、、他力本願。
Zopeに強く引かれたのってこんなことができそうな気がしたんだといまさら思ったりして。でもそれにはすごい労力が必要ということもすぐわかったけど。。。
日本語が当たり前につかえて、フリーで、オープンソースで、ファイルのバージョン管理ができて、Officeと連携ができて、なんてね。
いろいろ考えるとMS製品を使わざるをえないのか、今のところ。それかノーツ??うーーん。
Ajaxってなに??
あせあせ
日本のZope情報に
http://coreblog.org/jp/jzi/
atsさんがAjaxなWeb単語帳 を登録された。
なになに?Ajaxって。。
http://japan.cnet.com/special/story/0,2000050158,20082580,00.htm
こんな記事を発見。
ついでにMono Projecthttp://www.mono-project.com/Main_Pageについても検索
http://www.itmedia.co.jp/enterprise/articles/0406/24/news087.html
へーーー。最初Ploneかと思っちゃったよ。デザインが、、。
atsさんは本当によく勉強してるなー。日本のZope情報には私が全くよくわからない記事が投稿されてるのだけどそれを検索するだけでも勉強になります。
#検索しても全然わからんときも多いのですけどね。
カテゴリ、ジャンルがついたし、フッターにナビゲータがついて過去にさかのぼれるようになった。
昔読んだあの記事、を探す手段ができました。有り難うございます。
ひさしぶりにトラックバック打ってみます。
Reactをつかってみる
http://coreblog.org/ats/moblog2005-12-13-18-25
atsさんに教えていただいた
http://timmorgan.org/wiki/ReactFrameworkForZope
Reactなる物を使ってみる。
RDBをマッパーするものでありRuby on Railsを意識して作ったようです(object-relational mapper)。
まず、Readmeなどをあさったり、Helpをみたが懇切丁寧とは言えないかな、というHelpであった。なのでサンプルとしてブックマークを作ってみました。
http://nakaj.net/testFirebird/react/home/index
まず、ReactをいつものパターンでZopeに追加。
Productフォルダに拾ってきたファイルを展開。
任意の場所にReact Application Folderをまず追加しますとcontrollers,helpers,models,public,viewsというフォルダ群ができあがります。またReact Application FolderのHelpがGetting start...になっておりますので、基本的なサンプルコードはここを参照してください。
#というか、このGetting startで理解できる人は以下を読む必要ないです。
まずmodelsフォルダにいきましょう。
そこにお好きなDAを追加してやります。わたしはFirebirdを使いたかったのでKInterbasdbDAを追加しました。
TableをFirebird上に作ります。
こんなTable
create table bookmarks(
ID INTEGER Not Null,
URL VARCHAR(255) Nullable,
NAME VARCHAR(255) Nullable,
DESCRIPTION VARCHAR(255) Nullable,
Primary key (ID)
);
そしてReact Modelを追加します。
db_idは作ったTableの名前、bookmarksにします。TableはIDというカラムが必須でなおかつオートインクリメントがつかえるRDBMSなら、そうするのが楽なようです(Firebirdでもトリガーとジェネレータで同じような機能をつくれますが、ここでは行いません)。
そしてcontrollersフォルダへ移動し'home'という名前のパイソンスクリプトを作成します。
内容は以下のような感じとしました(笑わないでね)。
class home:
layout = 'application'
def index(self):
self.bookmarks = models.bookmarks.find_all()
def view(self):
self.bookmark = models.bookmarks.find(params['id'])
def update(self):
bookmark = models.bookmarks.find(params['id'])
self.bookmark = bookmark
current_name = bookmark.NAME
bookmark.id = params['id']
bookmark.URL = params['url']
bookmark.NAME = params['new_name']
bookmark.DESCRIPTION = params['description']
bookmark.save()
page = 'view?id='+params['id']
self.pageRedirect(page)
def new(self):
tmp = models.bookmarks.find_by_sql("id = (select max(id) from bookmarks)")
tid = tmp.ID +1
bookmark = models.bookmarks.new(ID=tid, URL=params['url'], NAME=params['new_name'], DESCRIPTION=params['description'])
bookmark.save()
page="index"
self.pageRedirect(page)
def destroy(self):
bookmark = models.bookmarks.find(params['id'])
bookmark.destroy(params['id'])
page="index"
self.pageRedirect(page)
def pageRedirect(self,page):
request = container.REQUEST
RESPONSE = request.RESPONSE
RESPONSE.redirect(page)
return home
destroyは実は自分で改造してしまいました。本来サンプルに示されているとおり、
thing = models.things.find(123)
thing.destroy()
という上記のコードでレコード削除が可能なようですが、全くうまくいかなかったのでIDを指定することで削除可能にしてしまいました。
newのところで副問い合わせをつかっていますが、先に書いたようにオートインクリメントがつかえるDBMSならこれは必要なくなるでしょう。
また、本来データの保証が無いのでこういうことをSQL直発行はしちゃいけませんね。一応注記しておきます。
さて、こんどはviewsフォルダへ移動します(忙しいですね、こうやってフレームワークに縛られることによってMVCに沿ってアプリケーションを作りましょう、というプロダクトなんですね)。
そこにも先ほどつくった"home"に応対してやはりhomeというフォルダを作ります。なかにはこんどは上記のclass homeに対応したzptを追加していきます。
各メソッドごとにindex,view,update,new,destroyです。
このうちupdate,new,destroyは空のコードにしました(もっと賢い方法があれば教えてください)。
例えばindexはこんな内容
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body tal:define="results bookmarks;
start request/start|python:0;
batch python:modules['ZTUtils'].Batch(results,
size=10,
start=start);
previous python:batch.previous;
next python:batch.next">
<p>
<a tal:condition="previous"
tal:attributes="href string:${request/URL0}?start:int=${previous/first}"
href="previous_url">previous <span tal:replace="previous/length">10</span> results</a>
<a tal:condition="next"
tal:attributes="href string:${request/URL0}?start:int=${next/first}"
href="next_url">next <span tal:replace="next/length">10</span> results</a>
</p>
<table border>
<tr>
<th>ID</th>
<th>NAME</th>
<th>DESCRIPTION</th>
</tr>
<div tal:repeat="result batch" >
<tr>
<td><a tal:condition="result/ID" href="#" tal:attributes="href string:view?id=${result/ID}">
<span tal:replace="result/ID">ID goes here</span></a></td>
<td><a tal:condition="result/URL" href="#" tal:attributes="href result/URL">
<span tal:replace="result/NAME">NAME goes here</span></a></td>
<td><span tal:replace="result/DESCRIPTION">DESCRIPTION goes here</span></td>
</tr>
</div>
</table>
<p>
<form action="new">
<label>URI :</label>
<input type="text" size="60" name="url" />
<label>NAME:</label>
<input type="text" size="60" name="new_name" />
<br />
<label>説明:</label>
<input type="text" size="80" name="description" />
<br />
<input type="submit" value="追加">
</form>
</p>
<p>
<a tal:condition="previous"
tal:attributes="href string:${request/URL0}?start:int=${previous/first}"
href="previous_url">previous <span tal:replace="previous/length">10</span> results</a>
<a tal:condition="next"
tal:attributes="href string:${request/URL0}?start:int=${next/first}"
href="next_url">next <span tal:replace="next/length">10</span> results</a>
</p>
</body>
</html>
としておきます。
viewは
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body tal:define="result bookmark">
<form action="update">
<input type="hidden" name="id" tal:attributes="value result/ID" />
<label>URI :</label>
<input type="text" size="60" name="url" tal:attributes="value result/URL" /><br />
<label>NAME:</label>
<input type="text" size="60" name="new_name" tal:attributes="value result/NAME" /><br />
<label>説明:</label>
<input type="text" size="80" name="description" tal:attributes="value result/DESCRIPTION" />
<br />
<input type="submit">
</form>
<a href="index">BookMark一覧へ戻る</a>
</body>
</html>
こんな感じ。
なやんだのはZPTを私はほとんど使ったことが無かった点。
Zopeパーフェクトガイドを開いたが「げ、ZPT解説なし、じゃん」、、、。
しょうがないので再びかなり悩んだがふとZ Search Interfaceを使えばいいじゃん、ということに気付きちょっと反則だが一度z sql methodを追加しZ Search Interfaceに助けていただいた。
もちろんそのままでは使えないので手を入れましたが、おかげでZPT嫌いをいくらか克服できました。
(食わず嫌いでした)
うわ、なんか疲れた。元気が出たらもうちょっと読めるように修正します。
#atsさんご紹介有難うございました。
以下は使った感想ですが、まずFirebirdはdiarectによってカラム名が大文字で返したり、小文字で返したりするので注意が必要。
こうやってMVCで縛られて開発するというのはたとえ自分自身しかつかわないアプリケーションでも非常に見通しが良くなってすばらしい。
適当に思いつくままに作って後悔することの多い私には有効。
SQLを隠蔽することでこんなに楽ができるとは思いもよらなかった。昔ながらにz sql methodでやるとクエリー送信用のページを作って、結果表示のページを作って、SQLメソッドを書いて、中間処理をpython scriptで、、、、みたいにとっちからってしまうのだが、ReactがコードはcontrollにHTMLを返すものはViewにと強制してくれるので見通しが確保できる、とわかった。
debianでPlone再び
だめだ、すぐわすれる
行ってみましょう。
debianのインストールからだよ。
時間合わせ
apt-get install ntp ntpdate
としておくと時間を勝手に合わせてくれるようになってるらしいから、あらかじめやっとく。サーバの時間がずれてるとaptしたときに煩わしいから。
パッケージのアップグレード
W: GPG error:などとでたらそのエラーメッセージどおり
apt-get install gnupg
する。それから
cp /usr/share/apt/debian-archive.gpg /etc/apt/trusted.gpg
する。
apt-get upgradeとかしたときに"apt::force-loopbreak"オプションをつけろなどとでてくる。これは
apt-get upgrade -o APT::Force-LoopBreak=true
のようなことをやると強制的にインストールしてくれる。
しかしエラーが出てるのがX関連のパッケージだったので、すべて関連パッケージを削除してしまった。
aptt-get --purge remove .....
smpにする
Pen3単体ではPloneがとてもとろいことは前にわかってたのでDualにしてみた。
apt-get install kernel-image
をすると候補になるパッケージがいくつか出るのでそのなかから686系でsmpとついているやつをインストール。
再起動。
topコマンドでの確認は"1"して"W"でtopの設定を保存しとく。
やっとZope
apt-get install plone
で現時点でzope 2.86 Plone 2.1.2がはいったらしい。
それから
apt-get install plone-site
も、やっとく
で、ブラウザからアクセスすると
http://xxx.xxx.xxx.xxx:8081/manage
おいおい、初期ユーザ名と、パスワードわからんじゃないか。
/usr/lib/zope2.8/bin/zpasswd.py -u XXXXX -p XXXXX /var/lib/zope2.8/instance/plone-site/inituser
で上書きしちゃえ。あ、Zopeの再起動が必要ね。
/etc/init.d/zope restart
かな。それから
/etc/zope2.8/plone-site/zope.conf
をいじってお好みの設定にしましょう。
再度ブラウザからmanageにアクセスしてplone-siteを追加しましょう。
と、まあこんな感じでうまくいくんじゃないかなー?
ころころ変わるからついていけないよ。だから自分のためのメモ書き。意味がわからなくても怒らない、怒らない。。
Python Developers Camp 2007 Winterの感想
今回、仕事と家事で忙殺され自分自身なにができたのかなー、と考える。
まずPythonの勉強はまったくしなかった、、、。
仕事して自宅に戻ればサーバまわりの調整と動画配信のテスト、今回使う予定だった各種ツール、Skype FestoonとかSkype HighSpeedConferencing(結局こっちはうまく立ち上がらなかったなー)のテストなぞやって、さらに仕事以外で2つのサイトの立ち上げを手伝っていたから無理もない(といいわけしとこう)。
結果当初よりわかっていたことだったけど現地組の方にかなり負担がかかってしまったことは申し訳なくおもっております。動画配信にサーバ提供できます、と手を上げなければそんなこともなかったわけでー、、、。
意外だったのは思っていたより動画を見てくださった方がすくなかったこと。当初は最大20人くらいを想定していたのが今回最大ピーク値で二日目夜の8人(一日目のピークは6人、三日目は3人)。
それからDVカメラの撮影手伝いとか、エンコーダ用のPCの提供とか、各種機器の提供とか声がすくなかった、レスポンスがあまりよくなかったのも意外でした。(電源タップなぞ誰でも持ってると思うのですが)
あれ、なんかネガティブになっちゃたな。
えーーっと、次回動画配信サーバの要請があれば(これだってWindowsサーバの基本機能だから提供できる人はいるはずだし)今回程度の規模でしたら喜んで提供しますが、今回のように自分から手を挙げることはしないことにいたします。
#やっぱネガだ、、、でも自分に負担がかかるのはともかく、人に迷惑かけるのはよくないもんね。
あっと追伸。今回Pythonを勉強できなかったかわりにこれ(http://www.amazon.co.jp/exec/obidos/ASIN/4774130427/trivialtechno-22/?ref=nosim)今日買ってきましたー^^;