文書操作
リレーションを貼ってみるナリ
現状のデータベースはちょっとつまらないです。テーブルが一つだけでリレーションは張っていません。せっかくリレーショナルデータベースを使うのだから、やっぱりリレーションが張ってあるテーブルをいじってみたいなぁ。でもリレーションなんて難しいことやってみたことないしなぁ。できるのかなぁ…。
(いろいろ調べちゅう)
ということで、1時間くらいネットを徘徊したところで早速リレーションを張ってみたいと思います。
リレーションて何
リレーションというのは関連づけということです。例えばこんなテーブルを考えてみます。
| name | email | age | city | company | co_location |
|---|---|---|---|---|---|
| a | a@hoge.com | 28 | shibuya | hoge | chiba |
| b | b@hoge.com | 37 | minato | hoge | chiba |
| c | c@hoge.com | 55 | meguro | hoge | chiba |
| d | d@fuga.com | 33 | yokohama | fuga | kanagawa |
| e | e@fuga.com | 41 | totsuka | fuga | kanagawa |
| name | email | age | city | co_id |
|---|---|---|---|---|
| a | a@hoge.com | 28 | shibuya | 1 |
| b | b@hoge.com | 37 | minato | 1 |
| c | c@hoge.com | 55 | meguro | 1 |
| d | d@fuga.com | 33 | yokohama | 2 |
| e | e@fuga.com | 41 | totsuka | 2 |
| co_id | company | co_location |
|---|---|---|
| 1 | hoge | chiba |
| 2 | fuga | kanagawa |
ここでこの二つのテーブルを関連づけているのは「co_id」というフィールドです。すなわちこのフィールドを接着剤にして二つのテーブルをリンクさせている(リレーションを張っている)わけです。
リレーションいろいろ
リレーションを張るときに大切なのは、どんなリレーションにするかということです。リレーションの種類として代表的なのは次のようなものです。
- 1対1の関係
- 例えばお菓子テーブルとバーコードテーブルという二つのテーブルを考えてみると、それぞれのレコードは1対1の関係にあります。この二つのテーブルは1対1のリレーションにあります。
- 1対多の関係
- 例えばお菓子テーブルとメーカーテーブルという二つのテーブルを考えてみると、メーカーテーブルのレコード1つに対して、お菓子テーブルのレコードが複数対応します(例えばメーカーAは商品Aも商品Bも商品Cも製造している、など)。一方お菓子テーブルのレコード1つに対するメーカーテーブルのレコードは1つだけです(例えば商品Aを製造しているのはメーカーAだけである、など。共同開発とか特殊な事情は考えません)。このときこの二つのテーブルは1対多のリレーションにあります。
- 多対多の関係
- 例えばお菓子テーブルと販売店テーブルという二つのテーブルを考えてみると、お菓子テーブルのレコード1つに対して、販売店テーブルのレコードが複数対応します(例えば商品Aは販売店Aでも販売店Bでも売っている、など)。一方販売店テーブルのレコード1つに対してもお菓子テーブルのレコードが複数対応します(販売店Aでは商品Aも商品Bも売っている、など)。このときこの二つのテーブルは多対多のリレーションにあります。
Turbogearsプロジェクトのテーブルを増やしてリレーションを張る
以上をふまえて、現在のデータベースに新たにテーブルを作成し、既存のテーブルとリレーションを張ってみたいと思います。
テーブルの変更と追加
現在データベースにはお菓子に関するテーブルがあります。
* クラス名は先頭大文字の方がよさげなので「snack」→「Snack」と変更し、またnameフィールドに64文字の制限をつけました(´ω`)
#model.pyの中身
class Snack(SQLObject):
name = UnicodeCol(length=64)
eval = IntCol()
comment = UnicodeCol()
ここにメーカーに関するデータのフィールドを加えていきたいと思います。とりあえず何も考えずにメーカーの名前を入れるフィールドを追加することにします。
#model.pyの中身
class Snack(SQLObject):
name = UnicodeCol(length=64)
eval = IntCol()
comment = UnicodeCol()
maker = UnicodeCol() ←メーカーの名前が入るフィールド
この段階では、ただ単にフィールドを増やしただけです。リレーションは張っていません。
リレーションを張る前にメーカーに関するデータを入れるテーブルを用意しなければいけませんね。メーカーテーブルには、メーカーの名前とそのメーカーが製造したお菓子のフィールドを用意することにします。こちらも何も考えずテーブルを書きます。
class Maker(SQLObject):
name = UnicodeCol(length=64)
snacks = UnicodeCol()
この段階では、ただ単にテーブルを追加しただけでリレーションは張っていません。
リレーションを張る
テーブルが二つできたところで双方にリレーションを張ってみたいと思います。このSnackとMakerの関係は「1対多」です。Maker(1)に対してSnack(多)のデータがあります。
Snackテーブルに注目してみると、makerフィールドというのが他のテーブル(Maker)からデータを引っ張ってきたい部分です(現時点では便宜上UnicodeCol()としてあります)。ここにはMakerテーブルから引っ張ってきたメーカーの名前が「1」個だけ入ってほしいところですので、外からのデータ(ForeignKey:外部キー)が入りますよということで、
maker = ForeignKey('Maker')と書いてあげます。
今度はMakerテーブルに注目してみると、snacksフィールドというのが他のテーブル(Snack)からデータを引っ張ってきたい部分です(現時点では便宜上UnicodeCol()としてあります)。ここにはSnackテーブルから引っ張ってきたお菓子の名前が「多」個入ってきて欲しいところですので、複数個のデータが入りますよということで、
snacks = MultipleJoin('Snack')と書いてあげます。
* 当初の計画ではメーカーに関するデータ表示などの機能は考慮にいれていませんでしたが、計画に追加することにします。
まとめると、「1対多」の関係の場合は、
- そのフィールドに他のテーブルから1個のデータが入る→ForeignKey('他のテーブル名')
- そのフィールドに他のテーブルから複数個のデータが入る→MultipleJoin('他のテーブル名')
という関係になりましょうか(ホントかな…)。
ということで、最終的にmodel.pyは以下のようになりました。
from sqlobject import *
from turbogears.database import PackageHub
hub = PackageHub("snack")
__connection__ = hub
class Snack(SQLObject):
name = UnicodeCol(length=64)
eval = IntCol()
comment = UnicodeCol()
maker = ForeignKey('Maker')
class Maker(SQLObject):
name = UnicodeCol(length=64)
snacks = MultipleJoin('Snack')
うーん、すごく自信ないんですが、これでいいんでしょうか。
- カテゴリ
-
Turbogears
- 固定リンク
- ¦
- コメント (0)
- ¦
- トラックバック (0)
- トラックバック用URL:
- http://nagosui.org/Nagosui/COREBlog2/make-relation/tbping

