Django と South と custom sql

自前で create table したい
Django を使っていて Django の ORM はそのまま使いたいんだけど、create table は自前で行いたい場合があります。
良くあるのは、partition 切りたい場合とか。
MySQL の range partition を使うには Primary Key を 複合Primary Key にする必要があるのですが、Djangoは 複合Primary Key を許可していません。
なので、そのような場合は自前で create table文 を書いて実行する必要があります。

class PartitionExample(models.Model):
    log = models.TextField(verbose_name=u'ログ')
    created_at = models.DateTimeField(verbose_name=u'作成日時', auto_now_add=True)

    class Meta:
        db_table = 'partition_example'
        managed = False # こうすると syncdb でモデルが作られない

こんなモデルを書いて

CREATE TABLE partition_example (                                                                                                                                                                               
    id int AUTO_INCREMENT,                                                                                                                                                                                  
    log TEXT,                                                                                                                                                                                             
    created_at DATETIME,                                                                                                                                                                                         
    CONSTRAINT PRIMARY KEY (id, created_at)                                                                                                                                                                      
)                                                                                                                                                                                                           
PARTITION BY RANGE COLUMNS (created_at) (                                                                                                                                                                        
  PARTITION pfuture VALUES LESS THAN (maxvalue)                                                                                                                                                             
);   

それと構造が等しい sql を書く。
その sql を appname/sql/partitionexample.sql に置くと、syncdb する時に自動的に sql を実行してモデルを作成してくれるという案配です。
いやー Django って良く出来てますね。
ところが、このままだと South 環境では上手く行きません。


South の場合
South を入れていると syncdb を上書いてしまっているので、sql を実行してくれないのです。
そこで、どうするかと言うと、schemamigration --init を実行すると managed = False のモデルを無視した migration ファイルが出来ます。

class Migration(SchemaMigration):
    def forwards(self, orm):
        pass
    def backwards(self, orm):
        pass

他にモデルがない場合はこんなの。
これを自前で sql を実行するように修正します。

class Migration(SchemaMigration):
    def forwards(self, orm):
        with open(sql_file_path) as f:
            sql = f.read()
        db.execute(sql)
    def backwards(self, orm):
        pass

これでOK。あとは普通に migrate するだけです。
これ以降の変更は schemamigration --auto で自動的に migration ファイルを作ってくれるので、普通に South を使う時と何も変わりません。

PyCon JP 2012 終わりました

初日
誘導を手伝った後、発表者用受付にほぼずっといました。
発表は何も見ていません。

夕方からはPartyの準備とか受付とかをしてました。
参加者が少ないのではないかと心配していたのですが、思ったよりずっと当日参加が多かったのと、会場が素晴らしかったおかげで参加した皆様に楽しんで頂けたみたいで良かったです。

二日目
初日頑張り過ぎたので寝坊して開場前の準備はパス。
午前中は初日と同じく発表者用受付にいました。
二日間とも受付をお願いしちゃった上に僕よりちゃんと対応してる@RicoImazu には頭が上がりません。

午後は基調講演だけ聞いて、後はなんか色々雑用してました。
@dankogaiさんの基調講演は賛否両論ありましたが、そもそもPython第一言語でない人にPyConに興味を持ってもらおうと「Pythonをdisって頂いても構いません」ってオファーをしているので…
不快な方もいたでしょうし、そういう方には申し訳ないと思いますが、プロレスで盛り上がった面もあると思うので個人的にはあれはあれで良かったかな、と思っています。
企画したパネルディスカッションが司会の@ymotongpoo と登壇者の皆様のおかげで盛り上がっていて一安心。
流石に疲れていたので、打ち上げにも参加せず帰宅。

三日目
Sprintにも参加せずに寝てました。
それなのに、翌日も寝坊したのは秘密です。

感想とか
「楽しかったー」って言うよりは「終わったー」「疲れたー」って感じでした。
今年はちょっと頑張り過ぎた。
発表見ないで働きっぱなしとかないわ。
来年は関わるにしても、もうちょっと力を抜こう。
そう思いつつ、来年の会場を探したり反省会の幹事をやってたりする辺り救われません。
あ、来年はAPACなのでスタッフしてくれる方を募集しています。
スタッフが増えれば今年の僕みたいなことにもならないと思うので、是非お願いします!

PyCon JP 2012 始まるよー

PyCon JP 2012 開催します!
以前「何故PyConJPの運営に関わっているのか」で書いたように、今年はスタッフとしてがっつり関わってました。

プログラム選んでタイムテーブルを決めたり

講師の方にハンズオンをお願いしたり

Partyの手配をしたり

開催前レポート書いたり

PyCon JP 2012 開催前レポート 第2回 主要セッションの見どころ紹介

PyCon JP 2012 開催前レポート 第3回 ハンズオン・パネルディスカッション紹介

ちょっと責任範囲多過ぎだろって思いつつ頑張ってましたが、それもこれもようやく報われるかと思うと胸アツです。

当日は会場の受付やPartyの受付をしていると思うので、見かけたら声をかけてくれると泣いて喜びます。


残念ながらチケットは既に完売しているのですが、YoutubeのPyConJPチャンネルでライブ配信されるので、チケットが買えなかった方は是非見てください。

日本における年に一度のPythonの祭典を、明日からの3日間思う存分楽しみましょう!

DjangoのGenericForeignKeyとdumpdata

GenericForeignKeyって使いにくい
DjangoのGenericForeignKeyってdumpdata→loaddataするとデータがズレるし使えないよねーって思ってた時期が僕にもありました。
なんでかって言うと、contenttypesの順番がsyncdbする度に変わるから、dumpdataした環境とloaddataした環境でcontenttypesが変わっていて別のモデルに紐付けられちゃうんですね。
前職ではそれを回避するために、対象のモデル群を固定で持ってるGenericForeignKeyっぽいモデルを自前で作ったりもしてました。


でも、そんなことなかった
Django1.2からdumpdataがGenericForeignKeyに対応していたらしく --natural オプションを付ければ問題なくloaddata出来るようになってました。
dumpdataしたjsonを見ればわかるのですが、オプションなしだとcontenttypesのidが入っている箇所がモデル名になっています。
これで気兼ねなくGenericForeignKeyを使えますね!

何故PyConJPの運営に関わっているのか

はじめに
去年もスタッフをやっていたPyConJP2012に今年も関わっています。
去年は途中から参加したのもあってあまり何もしていなかったのですが、今年は何の因果か色々と働いています。
Call for Proposal出してよー」
とか
スポンサー募集中だよー」
とか言ってると
「スタッフやるなんて凄いねー」
みたいな話をされることがあります。
しかもそれが僕なんかより全然凄い人達だったりするので、
(自分も他人も)勘違いしないように全然大したことなんかじゃないってのを記しとくのも良いかなーって思って筆を取ってます。
というか「Pinaxでサイト作るのとか面倒なんじゃよ」って言うただの逃避です…


スタッフやるのってどんな人だと思いますか?
普通イベントのスタッフやる人って

  • 意識が高い
  • 言語が大好き
  • コミュニティ大好き
  • お祭り大好き
  • お世話になってるものに貢献したい

こんな人じゃないかと思うのですが、僕はそういうの全くないのです。
そもそも去年のPyConJPもスタッフじゃなかったら、チケット買って朝起きるのが面倒で行ってなかったんじゃないかってくらい。
死んだ方が良いくらいダメ人間ですね><


じゃ何故去年はスタッフをやったの?
ふと「Python長く使ってる割に仕事で関わる以外の知り合い少ないなー」って思った時に、たまたまスタッフの募集をしていたので、何の気なしに応募してみただけです。
とは言え参加してみたら、スタッフは僕が唯一定期的に顔を出す勉強会の人や同僚が半数以上を締めていて、知り合いはあまり増えなかったんですけどね><
ただその分普通にとけ込めたというか、そもそもMTGを社内でやっていたって地の利もあって何となく続けていた感じです。
去年はParty用の店探したり、当日死にそうな顔で道案内をしていたくらいしかしてなかったし。


何故今年は色々やってるの?
なんででしょう?僕が知りたいです。
強いて言えば、なりゆきですかね。
去年スタッフをやられた方が今年は忙しい人多かったりで少なかったってのが大きいと思います。
「社内でMTGやるなら出るかー」
「あれ、人いなくね?」
「やる人いないならやりますよー」
みたいなノリです。
安請け合いして今困ってる訳ですが…
なんか自分が適当過ぎて泣けてきた><


これ以上深く考えると欝になるので、そろそろ宣伝を
PyConJP2012はまだまだ色々なものを募集しています。

他にも、LTとか当日スタッフとかも募集予定です。
特にスタッフはまだまだ足りてないです。
こんな適当な僕でも色々と出来てるくらいなので
「大変なんでしょう?」
とか
「そんな志もないしなー」
なんて考えずに気軽に応募してください。

rediscoの利点と欠点と正しい使い方

はじめに
プロジェクトぽしゃって気力失ってたけど、どこかで誰かが使おうと思った時のために残しておく。

rediscoの使い方等は以下を参照
http://d.hatena.ne.jp/flag-boy/20110601/1306902308


rediscoの利点

1. Key-Valueじゃないデータ構造が扱いやすい
redisco とは RedisDjango モデルっぽく使えるようにしてくれるライブラリってだけあって、通常のKey-Valueじゃない構造が扱いやすくなっている。
特に、idを自動で振ってくれるのでkeyを自分で考える必要がない のは便利。

2. 検索がしやすい
普通のKey-Valueだとkeyが決まってないと値を取得出来ないため、条件に合うものを探し出すのとかは面倒。
その点rediscoはindexを張ってくれるので条件に合うものの取得が簡単。
複数の条件の組み合わせは不可だが、単一の条件であれば(例えば四角形の場合縦でも横でも)検索可能。


rediscoの欠点

遅い

当たり前っちゃ当たり前なんだけど、1つのモデルは複数のデータから出来ているので、その分遅い。
Djangoモデルと同じような感じで使おうとすると、redis使ってる意味ないじゃんってくらい遅くなる。
特にsave()が致命的に遅い。indexを更新してるからしょうがないんだけど。


rediscoの正しい使い方

indexの更新が重いならindexをなるべく張らないようにすれば何とかなるんじゃないかって?
そう思ってた時期が僕にもありました。
ところがそう単純ではなく、indexを張ってなくてもフィールドがあるだけで重くなる。
具体的にはindexを張ってないフィールドでもsave()一回につきwriteが2回走る。
結局軽くするにはフィールドを減らすしかないので、indexを張ってない(検索しない)フィールドはこんな風に1つにまとめる必要がある。

  • モデル定義
from redisco import models
class Animal(models.Model):                                                                                                                                                                                                                                                                                                                                                          
    animal_type = models.IntegerField(required=True)                                                                                                                                      
    area_id = models.IntegerField(required=True)                                                                                                                                            
    params_attr = redisco_models.Attribute(required=True,                                                                                                       
                                                                  default='', indexed=False)

params_attrはdictのpickleにして、検索しないものを全てここにまとめてある。
実際のプロダクションではsetterやgetter書いたりしてparams_attrの中をもっと使いやすくしてたけど、その辺は割愛。
こうすることでwriteの回数が減ってようやくマトモな速度で動くようになった。


まとめ
・redisを使って検索もしたいときとかは凄く便利
・というか他の用途で使うのはない
・使う場合は検索しないフィールドは極力減らす

PyConJPでスタッフしてました

せっかくだから何かお手伝いしたいなーってことで、
夏前からスタッフ登録をしてちょっとしたHPの修正とかをやってました。
当日はこんな格好で誘導したり

Partyの受付をしたりしてました。
大した事は出来なかったけど、次回もまたお手伝い出来たらなって思います。