DjangoとMySQL
Pythonのフレームワークの1つDjangoをインストールした.
■ セットアップツールのインストール
setuptools-0.6c6-py2.4.eggを http://cheeseshop.python.org/packages/2.4/s/setuptools/よりDLした.
# /bin/sh setuptools-0.6c6-py2.4.egg
■ Python から MySQL に接続するためのモジュールのインストール
# easy_install -U -Z MySQL_python
■ Djangoのインストール
http://www.djangoproject.com/download/0.96/tarball/からDLした.
# tar xzvf Django-0.96.tar.gz
# python setup.py install
で終了なんですがー 2のインストールをしようとしたときに, /usr/bin/ld: cannot find -lmysqlclient_r というエラーがでてインストールすることができなかった. これは自分が以前にインストールしたMySQLが「--enable-thread-safe-client」オプションをつけてインストールしなかったため,スレッドセーフなクライアントライブラリ libmysqlclient_r が作成されていなかった…. ということで,MySQLを再インストールして無事成功!!
※ ldconfig でMySQLのライブラリを参照できるように設定したりはしました.
※ 今回の環境は, FedoraCore5, MySQL5.0.26, Python2.4.2 でした!!
Rails と Django 比較 ~テーブル作成~
今回は,データベース作成についてチョロっと書いていきます. それぞれのフレームワークは,もちろん自分でSQLを書いてテーブルを作成することはもちろん可能ですが,SQLを書かずに,またデータベースの方言なんてーのも意識しないで,大幅に少ない記述でテーブルを作成できるようになってます. てことで,それぞれのフレームワークで掲示板(BBS)のテーブル作成をしてみようと思います.
CREATE TABLE test (
id int not null auto_increment primary key,
user_id int not null,
title varchar(30),
message text not null,
create_time datetime not null
update_time datetime not null
delete_flag tinyint(1) default 0
);
- ※ create_timeは,メッセージを新規で投稿された日時を(自動)記録.
- update_timeは,メッセージの最終更新日時(新規の時は投稿日時)を(自動)記録.
- ■ Rails
- Railsでは,マイグレーション(migration)機能を利用してテーブルを作成することができます. ※ 既にプロジェクト(ここではdemoプロジェクトとする)が作成されており,データベースの設定(database.yml)が完了しているとする.
まずジェネレータを使ってマイグレーションの雛形とモデルの雛形を作成する.
migrationの雛形だけを作成してくれるジェネレータオプション(./script/generate migration)もあるのですが,同時にモデルを作成してくれた方が便利なのでこちらを使用した.
ジェネレータによって作成されたマイグレーションの雛形を編集する.
$ vi db/migrate/001_create_bbs.rb
class CreateBbs < ActiveRecord::Migration
def self.up
create_table :bbs do |t|
t.column :user_id, :integer, :null => false
t.column :title, :string, :limit => 30
t.column :message, :text, :null => false
t.column :created_at, :datetime, :null => false
t.column :updated_at, :datetime, :null => false
t.column :delete_flag,:boolean, :null => false, :default => false
end
end
def self.down
drop_table :bbs
end
end
作成日時(create_at)と最終更新日時(update_at)は,上記のCREATE SQLでいうcreate_timeとupdate_timeです. これは,railsが用意してくれている特殊なフィールド名でこのフィールド名にすると目的の自動記録というのが可能となる. ちなみに,特殊なフィールドには他に下記のようなものがある. created_at, created_on, updated_at, updated_on, lock_version, type, id, #{table_name}_count, position, parent_id, lft, rgt
では,実際にテーブル作成を実行する.
$ rake migrate
こうして出来上がったテーブルを参照すると
> use demo_development // demo開発プロジェクト
> describe bbss //
+-------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| user_id | int(11) | NO | | | |
| title | varchar(30) | YES | | NULL | |
| message | text | NO | | | |
| created_at | datetime | NO | | | |
| updated_at | datetime | NO | | | |
| delete_flag | tinyint(1) | NO | | 0 | |
+-------------+--------------+------+-----+---------+----------------+
- ■ Django
- Djangoでは,モデルにテーブルの情報を書いて,それをデータベースに反映させることで作成する.
railsのようにテーブル作成部分とモデルという部分を分けていない.
※ 既にプロジェクト(ここではdemoプロジェクトとする)が作成されており,データベースの設定(settings.py)が完了しているとする.そこにbbsというアプリケーションを作成するという形にする. まずbbsアプリケーションの作成をする
$ ./manage.py startapp bbs
これを実行することで次のようなディレクトリが作成される.
bbs/
+ __init__.py
+ models.py
+ views.py
作成されたmodels.pyの中に作成したいテーブル情報を記述していく.Djangoではアプリケーション単位でモデルが1つ用意され,そのファイル内にアプリケーションで使用するテーブル(クラス)を複数書いていく.さらに,作成したbbsアプリケーションを有効にするためにsettings.py のINSTALLED_APPSにdemo.bbsを追記しておく.
$ vi models.py
from django.db import models
class Bbs(models.Model):
user_id = models.IntegerField()
title = models.CharField(null=True, maxlength=30)
message = models.TextField()
create_time = models.DateTimeField(auto_now_add=True, editable=False)
update_time = models.DateTimeField(auto_now=True, editable=False)
delete_flag = models.BooleanField(editable=False, default=False)
auto_now_addは,オブジェクトを生成した時の時刻を自動的に設定します. auto_nowは,オブジェクトを保存する度にその時の時刻を自動的に設定します. editable=Falseは,今回の仕様で自動ということで,フォームと関連させないようにした.
また,Djangoはフィールドの定義に色々と変わったものが用意されている. たとえば,EmailField,IPAddressField,PhoneNumberField,などなどこれは直接バリデート,フォームと関連しているのでこんなのがあるのかなぁ〜.
次のコマンドを実行することで,発行するSQLが確認できる.個人的にこれ便利で好き.
$ ./manage.py sql bbs
BEGIN;
CREATE TABLE `test_bbs` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`user_id` integer NOT NULL,
`title` varchar(30) NULL,
`message` longtext NOT NULL,
`create_time` datetime NOT NULL,
`update_time` datetime NOT NULL,
`delete_flag` bool NOT NULL
);
COMMIT;
では,実際にテーブル作成を実行する.
$ ./manage.py syncdb
こうして出来上がったテーブルを参照すると
> use demo // 今回このプロジェクトで用意したデータベース
> describe bbs_bbs // アプリケーション名がプレフィックスとなる
+-------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| user_id | int(11) | NO | | | |
| title | varchar(30) | YES | | NULL | |
| message | longtext | NO | | | |
| create_time | datetime | NO | | | |
| update_time | datetime | NO | | | |
| delete_flag | tinyint(1) | NO | | | |
+-------------+-------------+------+-----+---------+----------------+
∞ ENDLESS THINK ∞ まぁ〜フレームワークとしての構造が元々違うってーのもありますがーこうやって同時平行して2つのフレームワークを勉強してみるとーもちろん頭はこんがらがりますがー1つのフレームワークずつやっているとー気付き難い部分がー気付けて面白いなぁ〜と思いますね. たとえば,railsとDjangoのどちらが個人的にテーブル作成しやすかったかというとrailsです. それは,僕自身がSQLを書けるからだと思います.マイグレーションに書くフィールドの型の指定の仕方は CREATE文から想像がつくでしょう!? さらに最大文字数の指定方法もlimitオプションというのがーなんともクエリを知っている感じ.ところが,Djangoは型の指定の仕方もー ○○Field なんて面倒なことを書き,最大文字数もmaxlengthというオプションを使う.
ここで気付くのがープログラマーではないデザイナー(HTMLを知っている人)だったらーどちらがわかりやすいかというとDjangoになるのだろう.だもんでーDjangoの場合は独特なフィールドの型指定なんてーのもあるんだろうね(バリデートも関わってくるのでしょうけど).
開発者達のどんな考えて,フレームワークを作成したのかなぁ〜と勝手な想像をするとまた面白い. テーブル作成というのも,どこのポディションに立ってデータベースを見つめているのかってねぇ〜
Django And Ajax
今週はDjangoに慣れるためにログインやブックマークなどを作成してみました.
jQueryを使ったAjax処理も組み合わせてやってみました.いやいやーやっぱ実際に作ってみるとートラブルばっかりですね. nobu さんにはお世話になっちゃいっぱなしでした.
Bookmarkは作成途中でーバグったまま….
ページャー&カスタムテンプレート
先日作成したBookmarkにページャーを追加してみました.
ObjectPaginatorと埋め込みタグ(inclusion tag)を使ってみました!! 最初くだらないところ "templatetags"ディレクトリの置き場とその設定(setting.iniに書く忘れててー) ではまっちゃいました.
ObjectPaginatorの使い方に関しては, 「/path/to/python2.4/site-ackages/django/views/generic/list_detail.py」 を参考にして作成.
Rails と Django 比較 ~テーブルの操作~
さてさて,せっかくBBSのモデル(BBSテーブル)を作成したので,レコードを追加したりしてみようと思います.
Django, Railsは,モデルクラスがデータベースのテーブルを表現し,クラスのインスタンスがレコードを表現する. それだけを頭に入れて,まずは色々やってみようと思う!! こんなものは動かしてナンボでしょ!?
- ■ Rails
□ オブジェクトの生成 俺のようなアホだと,オブジェクト生成と聞くと単なるインスタンス化すりゃいいのか?なんて思っちゃったりもする…データベースとの関係を忘れてしまっている…. ちゃんと最初の述べたコトを頭に入れてあれば問題ないはず. つまり,新しいBBSテーブルに新しいレコードを生成するってことですわっ!!
オブジェクトを作るには,newメソッドを使う. (メソッドっていう表現でいいのか? rubyの通常のインスタンス化させるときの命令です.実際は initialize(PHPでいう__construct)が引数を受け取れるメソッドになっている.)
bbs = Bbs.new(:user_id => 1, :title => "TEST TITLE", :message => "TEST MESSAGE")
もちろん,タイトルやメッセージはオブジェクトを作成してから設定することもできる.
bbs = Bbs.new bbs.title = "TEST TITLE" bbs.message = "TEST MESSAGE"
この時点では,まだDBにはレコードは追加されてないです.最後にsaveメソッドを実行することでDBに書き込まれます.
bbs.save
mysql> select * from bbs; +----+---------+------------+--------------+---------------------+---------------------+-------------+ | id | user_id | title | message | created_at | updated_at | delete_flag | +----+---------+------------+--------------+---------------------+---------------------+-------------+ | 1 | 1 | TEST TITLE | TEST MESSAGE | 2007-06-30 10:35:12 | 2007-06-30 10:35:12 | 0 | +----+---------+------------+--------------+---------------------+---------------------+-------------+
また,createメソッドを使ってオブジェクトを生成することもできる. これは,createメソッドを実行すると save まで行ってくれる. (createメソッドの中で,new(インスタンス化)してsaveを実行している. ん!? createメソッドってPHPでいう staticメソッドなのか?…やばっ…,ネイティブのrubyを知らないでやっていることがモロバレ!!! ちゃんと勉強しないとまずいですね.こういう俺のようなヤツが世にヒドイソースを散らすことになるのだろう(微笑))
Bbs.create(:user_id => 1, :title => "TEST TITLE", :message => "TEST MESSAGE")
□ オブジェクトの取得 今度は,上記で登録したレコード(オブジェクト)を取得する.
検索するには,findメソッドを使う.(他にも色んなメソッドがあります.)
IDによる検索例
bbs = Bbs.find(1) bbs.title # TEST TITLE bbs.message # TEST MESSAGE
もし見つからない場合は,「ActiveRecord::RecordNotFound」例外が発生する.
find :firstを使ったタイトルとメッセージによる検索例
bbs = Bbs.find(:first, :conditions => ["title = ? AND message = ?", "TEST TITLE", "TEST MESSAGE"])
もし見つからない場合は,「nil」が返ってくる.
find :allを使った対応するオブジェクトの全取得
bbs = Bbs.find(:all, :conditions => ["delete_flag = ?", false], :order => "updated_at DESC", :limit => 10)
もし見つからない場合は,「[]」が返ってくる.
□ オブジェクトの更新 単純に1度オブジェクトを取得し,変更箇所書き換えsaveする. たとえば,ID=1のタイトルを「DEMO TITLE」に変更する場合,
bbs = Bbs.find(1) bbs.title = "DEMO TITLE" bbs.save
mysql> select * from bbs; +----+---------+------------+--------------+---------------------+---------------------+-------------+ | id | user_id | title | message | created_at | updated_at | delete_flag | +----+---------+------------+--------------+---------------------+---------------------+-------------+ | 1 | 1 | DEMO TITLE | TEST MESSAGE | 2007-06-30 10:35:12 | 2007-06-30 11:00:56 | 0 | +----+---------+------------+--------------+---------------------+---------------------+-------------+
ちゃんと変更ができていて,かつ更新日も変更されている. しかし,あまりこの方法は取らないでしょうね….複数の項目の変更する場合は大変だし,saveなんて処理するのも面倒だしさ,だもんで,update_attributesメソッドを使う.
bbs = Bbs.find(1) if bbs.update_attributes(:title => "DEMO TITLE") // 成功処理 else // エラー処理 end
このメソッドは成功するとtrueが返ってくるので,このようにif文を使ってアプリを作っていくのでしょう.
- ■ Django
□ オブジェクトの生成 Bbsモデルクラスをimportして,Bbsモデルクラスのインスタンスを生成し,save()メソッドでデータベースに保存する.
from django.http import HttpResponse bbs = Bbs(user_id = 1, title = "TEST TITLE", message = "TEST MESSAGE") bbs.save() > select * from bbs_bbs; +----+---------+------------+--------------+---------------------+---------------------+-------------+ | id | user_id | title | message | create_time | update_time | delete_flag | +----+---------+------------+--------------+---------------------+---------------------+-------------+ | 1 | 1 | TEST TITLE | TEST MESSAGE | 2007-06-30 12:00:00 | 2007-06-30 12:00:00 | 0 | +----+---------+------------+--------------+---------------------+---------------------+-------------+
railsと同様,save()メソッドを実行して初めて,データベースに保存される. もちろん,タイトルやメッセージはインスタンスを作成してから設定することもできる.
from django.http import HttpResponse bbs = Bbs() bbs.user_id = 1 bbs.title = "TEST TITLE" bbs.message = "TEST MESSAGE" bbs.save()
また,create()メソッドを使ってsave()まで行う.railsと同じですね!
from django.http import HttpResponse Bbs.objects.create(user_id = 1, title = "TEST TITLE", message = "TEST MESSAGE")
objectsって突然出てきましたがー次に簡単に説明します.
□ オブジェクトの取得 オブジェクトを取得するには,モデルクラスのマネジャ(Manager)を使ってクエリセット(QuerySet)を構築する. クエリセットはデータベース上にあるオブジェクトの集まりを表現している. また,このマネジャはクラスに最低1つのマネジャがあり,デフォルトではobjectsという名前がついている. クエリを構築するには,filter()やexclude()を主に使う. (railsで言うfind()かと思うとーそれは間違い!! railsで言うfind()に近いのはget()になるでしょう.)
IDによる検索例
bbs = Bbs.objects.filter(id=1)
このとき得られた結果はクエリセットというものであり,けしてDB取得結果ではない.つまりbbs.titleなんてしてもエラーが 発生する. では,どんな時点でクエリが実行されるのかというと,クエリセットはfor文(イテレーション可能)などの操作を行った初めに実行される.
クエリ結果を返さず,DBの取得結果を返す場合は,
bbs = Bbs.objects.get(id=1) bbs.title # TEST TITLE bbs.message # TEST MESSAGE
もし見つからない場合は,DoesNotExist 例外を発生する.
タイトルとメッセージによる検索例
bbs_list = Bbs.objects.filter(title = "TEST TITLE", message = "TEST MESSAG")
railsのfind firstと結果を合わせるとすると,下記のように取得数を指定するべきかな!?
bbs = Bbs.objects.filter(title = "TEST TITLE", message = "TEST MESSAG")[:1]
[:1]は,SQLでいうLIMIT句のLIMIT 1を表現している. ちなみに,[:10 :25] OFFSET 10 LIMIT 15 という意味.
全てのオブジェクトの取得
bbs_list = Bbs.objects.all().order_by('-update_time')[:10]
order_by('-update_time')は,ORDER BY update_time DESC を意味する.
□ オブジェクトの更新 単純に1度オブジェクトを取得し,変更箇所書き換えsaveする. たとえば,ID=1のタイトルを「DEMO TITLE」に変更する場合,
bbs = Bbs.(1) bbs.title = "DEMO TITLE" bbs.save > select * from bbs_bbs; +----+---------+------------+--------------+---------------------+---------------------+-------------+ | id | user_id | title | message | create_time | update_time | delete_flag | +----+---------+------------+--------------+---------------------+---------------------+-------------+ | 1 | 1 | DEMO TITLE | TEST MESSAGE | 2007-06-30 12:00:00 | 2007-06-30 12:30:00 | 0 | +----+---------+------------+--------------+---------------------+---------------------+-------------+
railsのようなsave() 一緒に実行してくれるやつがあると思うのですが…. ちょっとどれかわからなかったのでー改めて書きます(笑)(汗)
∞ ENDLESS THINK ∞ いやぁ 0単なる1つのテーブルをやるだけなのにーこうやって書いてくと面倒やわぁ 0.本当はリレーション(railsではアソシエーション)を試してみたかったのに….
今回,自分的考えをねー図に書いたりして説明したいコトがあるんですがー難しくてね….図に表すのも面倒だけど 0図に表現するのもチト難しい.
簡単に,今回思ったことを述べるとぉ 0. railsとDjangoを比べるとーやっぱRailsの方がわかりやすいかなぁ 0と思っちゃう!! でもrailsの condition の設定方法はチト面倒くさい!! だけどーDjangoの方余計面倒くさい!? それは覚えることがrailsに比べると多いかも….最初「objects」ってなんだよ!! こんなモン毎回書かせるなっ!!なんて思っておりました.でも,Djangoというフレームワークを作成した開発者のこだわりみたいなものが見えてきてーちょっと考えを改めましたよ☆
どうもー彼等はテーブル間の操作とレコードの操作を分離したかったと….だからレコードを操作しようとするとー「objects」というマネジャを通してじゃないとー行えない.(実はこれをうまく図に書いて説明したいんだけど…できなかった.また,そこに適当に足を突っ込むとー余計疑問がでてきてしまうのでね…) これがわかるとー「ほほー,いいねぇ 0納得納得」となるよね.
また,今回触れませんでしたがーDjangoのクエリセットというのがー再利用という表現でいいのかなぁ 0. Aというクエリセットが,A1 = A.filter(X), A2 = A.filter(Y) とすることでAのクエリセットを利用して,A1とA2という別のクエリセットを作成することができる. これも気持ちいよね. クエリの実行のタイミングとか比較する場所は結構あるしー面白いところなんだけど….疲れちゃった…あはは….