お、画像が出てる

2007年02月28日(水) 01:20 この記事をクリップ!

 

最新Pythonエクスプローラの画像がamazonにも登場してた。

Djangoについて書いてます。買ってくだされ。

 あれー?JavaでWordドキュメントをつくるライブライリねーの?

2007年02月21日(水) 20:08 この記事をクリップ!

 

叫んだら誰かが助けてくれるかもしれないし…

JavaでWordドキュメントをきちんと生成できるライブラリって無いの?

poiのwordコンポーネントは止まってるし、iTextでrtfは画像がうまく出ないし、有償のものも見つからないぞ?

wordのxmlは事情により使えないんだなぁ。。。誰か助けて!

 現時点でのnewforms

2007年02月21日(水) 01:58 この記事をクリップ!

 

localflavorの登場でしかたなく、Djangoのnewformsをちょっとさわってみた。


Djangoの素敵な点として、モデルとしての特性は全てModelに記述するというものがあるわけだけど、現時点でのnewformsはどうなのかと。ちょちょいとさわってみただけなので、変かもしれないです。



まず、前提としてnewformsを構成するものたち。


  1. モデル + モデルフィールド
    データベースに対応するO/Rのモデルを意味する。
    モデルフィールドには型が有り、テーブル生成時やフォームフィールドの型はモデルフィールドから(デフォルトが)決まる。
    フォームフィールド生成ロジックはモデルフィールドにある。
  2. フォーム + フォームフィールド
    入力のバリデーションや、入力値(文字列)のPythonデータ化、保存ロジックまでを含むフォーム。
    oldformsのManipulatorのようなもの。
    ユーティリティファンクションで、モデルクラスやモデルインスタンスから生成可能。
    newformsが正式なformsとなった際には、汎用ビューにフォームも指定することになると思われる。
  3. ウィジェット
    HTML(とは限らないが)として表示する際に、どのようにレンダリングするかの部品。
    今回はウィジェットは無視


で、問題はlocalflavorに日本の郵便番号に対応するフォームフィールドを追加した場合に、どのようにそのフォームフィールドを使用するのかということ。



モデルがこんな感じだったとする。

from django.db import models
from django.contrib.localflavor.jp import models as jp_models
from django.contrib.localflavor.jp import forms as jp_forms
from django.contrib.localflavor.jp.validators import isValidJPPostalCode
from django.contrib.localflavor.jp.jp_prefectures import JP_PREFECTURES

class Address(models.Model):
    name = models.CharField(maxlength=50)
    postalcode = models.CharField(validator_list=isValidJPPostalCode, maxlength=8)
    pref = models.CharField(maxlength=16, choices=JP_PREFECTURES)

models.CharFieldを利用すると、フォームではnewforms.CharFieldが利用される。
ちなみに、現時点ではvalidator_listやchoicesを用いたバリデーションがnewformsでは行われない。



django.newforms.form_for_modelのformfield_callbackを使ってみる

formfield_callbackは、デフォルトではmodels.XxxField.formfieldを呼び出してnewforms.XxxFieldを返すようになっている。
from django import newforms as forms
from addressbook.address.models import Address
from django.contrib.localflavor.jp import forms as jp_forms
from django.contrib.localflavor.jp.validators import isValidJPPostalCode

def zip_field(f):
    if f.name == 'postalcode':
        return jp_forms.JPPostalCodeField(postal_validator= isValidJPPostalCode)
    return f.formfield()

AddressForm = forms.form_for_model(Address, formfield_callback=zip_field)
data = {'name': 'test', 'postalcode': '251-003', 'pref': 'kanagawa'}
f = AddressForm(data)
f.is_valid()
ヒドス


気を取り直して、django.newforms.form_for_modelのformにカスタムフォームを突っ込んでみる

カスタムフォームには、newforms.XxxField生成の振る舞いを変えたいものだけを定義すれば良い。
class AForm(forms.Form):
        postalcode = jp_forms.JPPostalCodeField(postal_validator= isValidJPPostalCode)

AddressForm = forms.form_for_model(Address, form=AForm)
data = {'name': 'test', 'postalcode': '251-003', 'pref': 'kanagawa'}
f = AddressForm(data)
f.is_valid()
んー。models.XxxFieldを定義した方がスマートだよねぇ。ここだけ振る舞いを変えるならまだしも、Addressモデルのpostalcodeは間違いなく郵便番号系のフィールドを使うんだから…。


Manipulator風にやってみる!

AddressForm = forms.form_for_model(Address)
AddressForm.base_fields['postalcode'] = jp_forms.JPPostalCodeField(postal_validator= isValidJPPostalCode)
data = {'name': 'test', 'postalcode': '251-003', 'pref': 'kanagawa'}
f = AddressForm(data)
f.is_valid()
うぬんうぬうぬorz

 Pythonにも勢いのいい人がでてきた

2007年02月17日(土) 02:03 この記事をクリップ!

 

Python使いにも、いい感じの勢いの人が出てきましたぁ。


lingrで、作ろうかなぁとつぶやいていたと思ったら数時間後には、なんとなくコードが出来てきたとか。


MiCHiLUさんは、勉強会でデモって!と言われればかなり詳細な説明文を用意し、出張Shibuya系懇親会を嗅ぎ付ければまぎれて出席し、ついでにYAPCのチケットを予約し、PyConに行こうと言われれば英語教材を申し込もうとする。そんな素敵な勢いの人が登場しました。


Django界隈は、なんとなく勢いのいい人が多いなと(TGの人にも勢いのいい人がいますが、頭数が足りない気が…)。


勢いのいいMiCHiLUさんとid:mopemopeさんが中心で作れば、やっとこさPythonのPlagger実装ができることでしょう。


 東京の嘘

2007年02月16日(金) 15:03 この記事をクリップ!

 

ZiGOROゥさんに、サクサカーですか?と聞きたかったのに聞けなかったのはおいておいて(※)。


センセィが…


映画に主演してる。『東京の嘘』(リンク先、いきなり音が出ます)。


どうでもいいから、昔みたいにキチンと小説書いてよ…



※ sakusakuを見ていたら東京の嘘の宣伝をしていたので、思い出して書いてみただけw。


 マウラたんのお手製クッキー

2007年02月15日(木) 23:04 この記事をクリップ!

 

今日もデブサミに行った。


「Ajax アーキテクチャとデザイン」のタイトルと内容の乖離具合が残念だったくらいで、おおむね昨年より楽しく過ごすことが出来た。


PyJUGブースの後ろでDjangoの布教活動を行いつつw。昨日と今日でPyJUGの名刺が無くなりモシタ。頑張った、俺。


日本のDjangoファンがファンなマウラたんの「手作りクッキーネタ」がアップされてましたよー


そうそう、PyJUGブースに「Django AMFに非常に興味がある」という方がみえました。地方の方だそうで、Django勉強会には参加できないとのことでしたが、やはり見る人は見ている!と思いました。

 デブサミ2007の出張シブヤ系イベント

2007年02月15日(木) 02:18 この記事をクリップ!

 

PHPのPlagger実装(名前空間を穢してはいけないということで改名予定)がhaltさんによってライトニングトークされるということで、出張シブヤ系イベントへ行ってきました。


PHPのPlagger実装は、モテ系だそうです。


ちょっと話変わって「IT戦記」の中の人のセッションにて「JavaScriptはそろそろLiveScriptっていう名前に戻ってもいいんじゃないか」という下りがありましたが、そうなるとShibuyajsはShibuyalsになって、ls -laな感じになりやしないかと一人ニタついていました。



イベント終了後、厚かましくもシブヤ系の人たちの打ち上げに混ざってきました。
ネット上で名前を耳にする有名人の人たちの中で小さくなっていました。
PHPの人たちとはまた違ったキャラで、噂通り一番元気がよい感じでした。


LドアやらHてなやらのうわさ話が聞けたりしました。「IT戦記」の中の人に、Pythonを是非是非と言えたので満足です。


PHP/Perlと来たので、あとはRubyの集まりに突撃です。3月のRails勉強会には突撃する予定です。


みんな!じゃんじゃん別の言語の勉強会に行こうぜー!
じゃんじゃん、じゃんご♫



家に帰ると、娘に頼まれ事があると嫁が。(実際には、チョコはー?と聞いてきたんだけど無視)

じゃじゃーん。3歳の娘と嫁の合作チョコが待ったたよー

チョコ(娘と嫁の合作)
チョコ(娘と嫁の合作) posted by (C)everes


娘は嫁の布団の下で寝ていた。

なぜか嫁の布団の下で寝てる娘
なぜか嫁の布団の下で寝てる娘 posted by (C)everes


 Pylaggerを夢想する

2007年02月14日(水) 12:20 この記事をクリップ!

 

RubyのPlagger実装も登場し、PRhagger(PHPのPlagger実装)が今日のデブサミでライトニングトークされる。世界的にはYahooPipesか。


残るはPythonだけなんだけど、ちょっと前から夢想しているもの。


誰かに作ってほしいPylagger


  1. プラグインはPylaggerのローカルWebアプリケーションから、インターネット上のプラグインリポジトリを検索できる。

  2. プラグインはリポジトリからPythonスクリプトの形で取得する

  3. 取得したPythonスクリプトは、コンパイルしたものをpickleしてデータベースに格納する。

  4. プラグインにはインナークラスで設定可能項目が定義されている

  5. 「一連のプラグイン(複数のinと複数のfilterと複数のoutを1セットにしたもの)」はPylaggerのローカルWebアプリケーションを用いて設定し、設定データはDB(pysqlite?)に格納される。

  6. 設定した「一連のプラグイン」は今は亡きdjangoutilsのジョブか、Twistedのジョブみたいので定期実行をする。

  7. Windows環境では、py2exeを用いてコンパイルし、ダブルクリックするだけで動作する。

  8. OSX環境では、cocoaでラップしGUIによるユーティリティが付属する。

PRhaggerの敷居の低さに対抗するインパクトに対抗するためには、言語自体もインストール不要とし、プラグインのインストールもファイルシステムを意識しないレベルでないといけないと思う。

 SoozyConference1

2007年02月14日(水) 00:00 この記事をクリップ!

 

[2007年02月23日(金)のイベント]

言語を問わないWeb Frameworkに関する勉強会。だそうだ。

とりあえず、メンツがヤベーのでへらへらしてよう。

 Django勉強会 Disc3

2007年02月14日(水) 00:00 この記事をクリップ!

 

[2007年03月10日(土)のイベント]

恒例の寺子屋(ペアプロ)の他に、Djangoでsenna(sennaの中の人登場)、rhaco(rhacoの中の人登場)、SQLAlchemy(TurboGears-jaのaodagさんが中継で登場)と盛りだくさんのDjango勉強会 Disc3。

参加しないと乗り遅れるよw

 俺ははてなが嫌いなんだ

2007年02月12日(月) 14:54 この記事をクリップ!

 

昔から嫌いだ。


その昔、Googleではなくてinfoseekを検索に使っていた頃から嫌いだった。
いわゆるドットコムの時代で、いまならweb1.0と呼ばれる時代のこと。フロント層の技術は今よりも貧弱な中、今と同じようなアプリケーションを作っていた時代のことだ。


当時はてなは、「人力検索」をメインにしていたのかもしれない。人力検索自体は他所もやっていて、特に特異ということもなかった。はてなが特異だったのは、「はてなキーワード」というwikiのような仕組み。同様の理由でwikiも嫌いだった。


「はてなキーワード」とwikiワードが嫌いな理由は、ユーザが敢えて張ったリンクと、機械が自動で貼ったリンクの区別をしなければいけないからだ。きちんとメンテされているwikiであれば、ページ作成のためのページを差し出されて怒り狂うことも無いのだけれど、大抵のwikiはキーワードだけしかない。


「はてなキーワード」が、よりひどいのは、リンクをクリックしてみると「はてなキーワードの説明ページ、と見せかけたアフィリエイトページ」にたどり着くことだ。アフィリエイトだということが分かりやすいページに、分かりにくいリンクで誘導される。そして、自サイトへのリンクをたくさん持ったページ、役に立たないキーワードへのリンクを手がかりに、検索エンジンの上位を汚していた。これが当時「俺がはてなを嫌いだった理由」だ(実のところ、当時からキーワードページにアフィリエイトがあったかどうかは定かではない)。



そして今、web2.0とバズられる時代。


2007年の節分の日、予告されていた時間よりも長く、メンテナンスのためにはてなのサービスが完全に停止した。


梅田望夫サロンがlingrで開催される日。しかも、梅田望夫サロンへの到達方法は梅田望夫さんのはてなダイアリーでされていて、非常に困った日。


やっと皆、はてなへの依存度に気づいたことだろう。そこでもう一つ、はたと気づくべきだったことに、ギーク達は気づかなかったろうか?


web2.0ってなんだっけ?ユーザが登録したデータはユーザのもの、という話ではなかったか?


もちろん、はてなは自サービスのことをweb2.0と言ったりはしていないけれど、きっとみんな思ってるんじゃない?「データは取り出せるし、他の類似サービスに移せるだろう」って。


はてなは、変な会社でうってるけど、実のところ変なところは一つもなくて、もし変なところがあるとすれば独立IT系にしては商売がうまい、っていうくらいだよね。


これが「今、俺がはてなを嫌いな理由」



え?今嫌いな理由はデータが取り出せないことだろうって?


ジョウダンハヨシコサン
今、はてなが嫌いな理由は、「商売がうまくて妬ましい」ってことだよ、当然。
チッキショー




あとは、iMacほしい!Wiiほしい!って叫んだのにあたらなかったことも、嫌いな理由である。


 SoozyConference行きたい!

2007年02月10日(土) 23:07 この記事をクリップ!

 

id:mopemopeさんじゃないけど、SoozyConference楽しそう。


スンゲー濃いメンツが集まるみたい。濃くないDjangoの発表じゃ行かれないのかな…


さすが閉鎖的を詠うだけあって、エントリ方法は書いてないな。


SoozyConference行きたい! と叫んでみたりする。


 DISる

2007年02月06日(火) 18:08 この記事をクリップ!

 

DISるってなにから来てるのか、常々不思議だったんだけどモヒカンのキーワードにありました


disrespectするの、略だそうです。


なぜ調べてみたのかというと、デブサミ渋谷系セッションのPRhagger発表者のコメントにDISるが登場していたからです。


そうです。デブサミでPRhaggerが発表されます(haltさんによるライトニングトーク)。今日知って、あわててrhacoな人も申し込んでました。ストラテクト研究所から、WorkStyleの非と含め、3人で見に行きます(ちょっと恥ずかしいw)。


 梅田望夫サロン at Lingr

2007年02月03日(土) 13:01 この記事をクリップ!

 

かなり楽しいLingrで、梅田望夫さんの公開部屋イベントが開催されたので、のぞいてみました。


負荷試験になるねー、とかいう話だったのですが、試験には合格できなかったようです。


一つの発言が、10人くらいが蹴りだされたというシステムメッセージと、10人くらいが参加したというシステムメッセージに挟まれる感じ(この間5分くらい?)。


anonymousの人が100人弱、チャットを開始している人が30人位?で、殆ど会話は出来ませんでした。


Django-ja部屋とか個々一番部屋とかはanonymous含めて20人強位なので、5〜6倍の人が使おうとしたことになります。ただ、C10Kは問題ないとかちょっとまえに議論がそこら中で行われていたことを考えると、「C1Kでも駄目じゃん」とか思ってしまいます。梅田望夫サロンの開始時刻ちょっと前からDjango-ja部屋もあおりを受けて蹴りだされる状態が続きました。


「ボットを送りんこんで悪戯したら、ひどい目に遭わされるかなぁ。駄目だよなぁ」とか夢想していたのですが、それどころではありませんでした。


API公開して盛り上げて、梅田望夫さん持ち込んで盛り上げて、というシナリオは分かりやすいですが…ミスですよね。順番間違えた感あり。


Lingrはまだまだこれからだと思うので、ぜひともC10Kに打ち勝ってほしいところです。


ドットコム時代に似たような実験をして、サーバがこけたことあるので気持ちは非常に分かりますw


 lingrのボットPython版

2007年02月02日(金) 16:24 この記事をクリップ!

 

うくくの人が作ったlingr用のPythonエコーボットをいじくって、会話から適当なサイトを推薦するボットにしました。


会話の文脈なんて知ったことじゃありません。インチキです。コードもインチキです(yahoo_searchんとこね)。


人の会話からひらがな以外をn個集めて、そのうちのm個を使ってYahooにお尋ねをします。


教えてくれたサイトから一つ、simpleapiのサムネイルとURLをボットが推薦します。


邪魔臭いです


# coding: utf-8
import urllib
from django.utils import simplejson
from BeautifulSoup import BeautifulSoup as Soup
from random import choice, randint

import re

#FIXME START
room_id = 'xxxxxx'
bot_nickname = 'xxxxxx'
yahoo_key = 'xxxxxx' #YAHOO.CO.JP Developer API application key
api_key = "xxxxxx" #LINGR API KEY
word_count = 12
word_count_for_query = 2
#FIXME END

_YAHOO_URL = 'http://api.search.yahoo.co.jp/WebSearchService/V1/webSearch?appid=%s' % yahoo_key
_SIMPLEAPI_URL = 'http://img.simpleapi.net/small/%s?.png'

_CREATE_URL = "http://www.lingr.com/api/session/create/"
_ENTER_URL = "http://www.lingr.com/api/room/enter"
_SAY_URL = "http://www.lingr.com/api/room/say"
_OBSERVE_URL = "http://www.lingr.com/api/room/observe/"
_GET_MESSAGES_URL = "http://www.lingr.com/api/room/get_messages/"


class Lingr(object):
        
    def __init__(self, api_key):
        self.api_key = api_key
        data = dict(api_key=api_key,format="json", client_type="human")
        r = urllib.urlopen(_CREATE_URL, urllib.urlencode(data))
        json =  r.readlines()
        json = simplejson.loads(json[0])
        self.session = json["session"]

    def enter_room(self, id, nickname="anonymous"):
        room = LingrRoom(self.session, id, nickname)
        return room        

class LingrRoom(object):

    def __init__(self, session, id, nickname):
        self.session = session
        self.id = id
        self.nickname = nickname
        data = dict(session=session,id=id,nickname=nickname,format="json")
        r = urllib.urlopen(_ENTER_URL, urllib.urlencode(data))
        json =  r.readlines()
        json =  simplejson.loads(json[0])
        self.ticket = json["ticket"]
        self.counter = json["room"]["counter"]
        self.word = []

    def yahoo_search(self, query):
        if not query:
            return None
        q = re.sub(u'[\u3041-\u3093 <><>:]', ' ', query).strip().encode('utf-8')
        self.word += [w for w in q.split(' ') if len(w) > 0]
        if len(self.word) < word_count:
            return None
        q = ' '.join([choice(self.word) for i in range(word_count_for_query)])
        self.word = []
        url = '%s&%s' % (_YAHOO_URL, urllib.urlencode({'query':q}))
        s = Soup(urllib.urlopen(url).read().replace('', ''))
        targets = s.findAll('result')
        if targets:
            [x.extract() for x in s.findAll('cache')]
            urls = s.findAll('url')
            if urls:
                neta = urls[randint(0, len(urls) -1)].string
                self.say(_SIMPLEAPI_URL % (neta,))
                self.say(neta)

    
    def observe(self, callback=None):
        data = dict(session=self.session,ticket=self.ticket,counter=self.counter,format="json")
        url = _OBSERVE_URL+"?"+urllib.urlencode(data)
        r = urllib.urlopen(url)
        json =  r.readlines()
        json =  simplejson.loads(json[0])
        try:
            self.counter = json["counter"]
            if callback:
                messages = json["messages"]
                for m in messages:
                    type = m["type"]
                    text = m["text"]
                    if type == "user" and text:
                        callback(text)
        except KeyError:
            pass
                    
    def say(self, message):
        message = message.encode('utf-8')
        data = dict(session=self.session,ticket=self.ticket,message=message,format="json")
        r = urllib.urlopen(_SAY_URL, urllib.urlencode(data))
        json = r.readlines()
        json = simplejson.loads(json[0])
        try:
            self.counter = json["counter"]
        except KeyError:
            pass
        
    def start(self):
        import time
        while 1:
            self.observe(self.yahoo_search)
            time.sleep(1)

    

if __name__ == '__main__':
    lingr = Lingr(api_key)
    room = lingr.enter_room(room_id, nickname=bot_nickname)
    room.start()
    

自己責任で

 TGとDjangoの温泉

2007年02月01日(木) 00:47 この記事をクリップ!

 

次から次へとlingrのdjango-jaでDjango企画が浮上中です。


今日は、TurboGearsとDjangoの仲間たちで温泉に行って、wiki20のタイムアタック!?


気になる人は、aodag兄さんとこか、voluntas兄ぃんとこか、djangoja@lingr見てください。マジでやるかやらないかはあなた次第。


続々の第一弾が気になる人は、django-ja@lingrのログを見てください。Xxxxx VS Djangoみたいなw


 Python Developers Camp 2007 Winter

2007年02月01日(木) 00:00 この記事をクリップ!

 

[2007年03月02日(金)のイベント]

Pythonに特化した合宿イベント「Python Developers Camp 2007 Winter