TurboTunes
TurboTunesチュートリアル
by Ronald Jaramillo
TurboGearsでApple社から市場シェアを盗みましょう
これはKevin Dangoorによる "TurboTunes"動画(19.3MB QuickTime) のテキストバージョンです。動画は Internet Archive や BitTorrent経由 でも入手可能です。
このチュートリアルではあなた専用のミュージックストアを TurboGears を使って実装する方法をご覧いただけます。 私たちが達成するために何を計画するのかを理解するには この短いクリップ をご覧ください。
私たちは以下のステップをカバーします:
新規プロジェクトの作成
tg-admin quickstart を使用して新しいTurboGearsプロジェクトの作成を開始します。 プロジェクトは TurboTunes と呼ぶことにします。
tg-admin quickstart
データベースの構成
プロジェクトのデータベースを作成し、dev.cfg と prd.cfg をあなたのデータベース設定に合わせて構成します。 私は postgres を使用しているのでこのようになりそうです。
[global] # DATABASE # pick the form for your database sqlobject.dburi="postgres://postgres@localhost/turboTunes"
モデルの定義
モデルファイル(model.py)を開き、モデルクラスの定義を開始します。 アーティストをジャンルでグループ分けしたいので:
class Genre(SQLObject):
name = StringCol(length=200)
artists = RelatedJoin('Artist')
このようなアーティストオブジェクトで多対多のリレーションを定義します。
class Artist(SQLObject):
name = StringCol(length=200)
genres = RelatedJoin('Genre')
albums = MultipleJoin('Album')
アーティストは(複数の)アルバムを作るので、新たにオブジェクトを定義します。
class Album(SQLObject):
name = StringCol(length=200)
artist = ForeignKey('Artist')
songs = MultipleJoin('Song')
そして、最後は楽曲です。
class Song(SQLObject):
name = StringCol(length=200)
album = ForeignKey('Album')
tg-admin sql create を実行するとテーブルが作成されるでしょう。
tg-admin sql create
そのまま続けたい、あるいはタイピングする気分でない場合には ここから モデルファイルをダウンロードしてください。
CatWalkをマウント
controllers.py ファイルを開き、次のようにしてCatWalkをマウントします:
import turbogears
from turbogears import controllers
from turbogears.toolbox.catwalk import CatWalk
import model
class Root(controllers.Root):
catwalk = CatWalk(model)
@turbogears.expose()
def index(self):
return dict()
モデルをインポートすることと、それをパラメータとしてCatWalkに渡すことを忘れないでください。
Webサーバを起動します。
python turboTunes-start.py
CatWalkが http://localhost:8080/catwalk で開始するでしょう。
ストアを生成
CatWalkを使用することで、あなたのストアをすばやく生成することができます。ジャンルの追加から開始して、アーティストを何人か追加します。 アーティストがどのジャンルに属するかを構成します。アルバムをアーティストに追加して、楽曲をアルバムに追加して… いくつかやると このクリップ のようになるでしょう。
コントローラの編集
コントローラを次のメソッドで実装します。
index
メインのHTMLテンプレートを提供します。
genres
ジャンルのリストを構築し、返します。
artists
リクエストされたジャンルに属するアーティストのリストを構築し、返します。
albums
リクエストされたアーティストに属するアルバムのリストを構築し、返します。
songs
リクエストされたアルバムに属する楽曲のリストを構築し、返します。
import turbogears
from turbogears import controllers
from turbogears.catwalk import CatWalk
import model
class Root(controllers.Root):
catwalk = CatWalk(model)
@turbogears.expose()
def songs(self,album):
a = model.Album.get(album)
return dict(rows= [[song.name,
song.album.artist.name,
song.album.name]
for song in a.songs])
@turbogears.expose()
def albums(self,artist):
a = model.Artist.get(artist)
return dict(selectID='albums',
options=[{'label':album.name,
'value':album.id}
for album in a.albums])
@turbogears.expose()
def artists(self,genre):
g = model.Genre.get(genre)
return dict(selectID='artists',
options=[{'label':artist.name,
'value':artist.id}
for artist in g.artists])
@turbogears.expose()
def genres(self):
return dict(selectID='genres',
options=[{'label':genre.name,
'value':genre.id}
for genre in model.Genre.select()])
@turbogears.expose(html="TurboTunes.templates.tunes")
def index(self):
return dict()
まだタイピングする気分ではありませんか? ここの コントローラファイルをダウンロードしてください。
テンプレートの編集
TurboTunes ミュージックストアは3つのセレクトボックスとグリッドビューで構成されます。 最初のボックスにはジャンルが一覧され、2番目はアーティスト、3番目はアルバムとなります。 グリッドビューには楽曲が表示されます。
テンプレート(templates/tunes.kid)には(CatWalkユーザがインターフェイスをレンダリングするために)MochiKitとWidgetsをインポートすべきです。 細かな機能をすべて引き出すには、いくつかの関数を書く必要があります。
init
bodyのonload関数から呼ばれるべきものです。 ジャンルのリストをロードして、グリッドを初期化します。
retrieveGenres
genresメソッドへのAjaxメソッドです。 loadListへのコールバックをセットします。
loadList
JSONデータ構造をセレクトボックスを生成するWidget.select.loadに渡します。
retrieveArtistForGenre
artistsメソッドへのAjaxリクエストで、選択されたジャンルをパラメータとして渡します。
retrieveAlbumsForArtist
albumsメソッドへのAjaxリクエストで、選択されたアーティストをパラメータとして渡します。
retrieveSongsForAlbum
songsメソッドへのAjaxリクエストで、選択されたアルバムをパラメータとして渡します。
loadTable
Widget.grid.renderを呼び出し、JSONデータ構造を渡します。
これは最も大きいプロジェクトファイルです:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:py="http://purl.org/kid/ns#" >
<head>
<meta content="text/html; charset=UTF-8" http-equiv="content-type" py:replace="''"/>
<title>TurboTunes</title>
<link rel="stylesheet" type="text/css" href="/tg_static/css/widget.css" />
<script src="/tg_static/js/widget.js"></script>
<script src="/tg_js/MochiKit.js"></script>
<style>
body,td { font-family:verdana,sans-serif; }
#top
{
background-image:url('static/images/topbg.png');
background-repeat:repeat-x;
height:70px;
font-size:10px;
color:#666;
font-weight:900;
}
select {width:255px;padding:0;margin:0}
.list_head {
height:17px;
font-size:10px;
color:#666;
font-weight:900;
text-align:center;
border-right:1px solid #666;
background-image:url('static/images/bg.png');
background-repeat:repeat-x;
}
.grid td {height:13px;font-size:10px;}
#app {border:1px solid #666 }
</style>
<script>
<![CDATA[
function loadTable(content)
{
var MIN_ROWS = 10;
content['headers'] =['Name','Artist','Album'];
var n = content.rows.length;
if( n < MIN_ROWS)
{
for(var i=0;i< (MIN_ROWS-n);i++)
{
content.rows[content.rows.length]=[' ',' ',' '];
}
}
replaceChildNodes('song_placeholder',Widget.grid.render('songs',content));
}
function loadList(result)
{
Widget.select.load(result['selectID'],result);
}
function retrieveGenres()
{
var e = loadJSONDoc('genres');
e.addCallback(loadList);
}
function retrieveArtistForGenre(list)
{
var id= list.options[list.selectedIndex].value;
var e = loadJSONDoc('artists?genre='+ id);
e.addCallback(loadList);
Widget.select.load('albums',{options:[]}); //clear the albums
loadTable({rows:[]}); //clear the songs
}
function retrieveAlbumsForArtist(list)
{
var id= list.options[list.selectedIndex].value;
var e = loadJSONDoc('albums?artist='+ id);
e.addCallback(loadList);
loadTable({rows:[]}); //clear the songs
}
function retrieveSongsForAlbum(list)
{
var id= list.options[list.selectedIndex].value;
var e = loadJSONDoc('songs?album='+ id);
e.addCallback(loadTable);
}
function init()
{
loadTable({rows:[]});
retrieveGenres();
}
]]>]]><![CDATA[
</script>
</head>
<body onload="init()">
<table width="100%" cellpadding="0" cellspacing="0" border="0">
<tr>
<td align="center">
<table id="app" cellpadding="0" cellspacing="0" border="0">
<tr>
<td colspan="3" id="top" align="center">
TurboTunes
<br />
<img src="static/images/tg.png" />
</td>
</tr>
<tr>
<td class="list_head">Genre</td>
<td class="list_head">Artist</td>
<td class="list_head">Albums</td>
</tr>
<tr>
<td valign="top"><select name="genres" id="genres"
onchange="retrieveArtistForGenre(this)"
size="15"></select></td>
<td valign="top"><select name="artists" id="artists"
onchange="retrieveAlbumsForArtist(this)"
size="15"></select></td>
<td valign="top"><select name="albums" id="albums"
onchange="retrieveSongsForAlbum(this)"
size="15"></select></td>
</tr>
<tr>
<td colspan="3">
<div id="song_placeholder"></div>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
ここで 取得してください。