GAEpでiPhone向けWebアプリを作る (5)GAEp 上にモデルを定義する
前回の続きです。
GAEp 上にモデルを定義する
ようやくGAEpのソースコードが出てきます。
モデルの整理
今回の ToDo アプリで必要な要件を整理します。
* ひとつの ToDo を表すアイテム(ToDo アイテム)が存在する
* ひとつの ToDo アイテムは、必ず誰かのアイテムである(必ず誰かが所有する)
* ひとつの ToDo アイテムには、いつまでに何をなすべきか、が指定されている
非常に簡単です。
モデルを定義する
以下のようにモデル(カインド)を定義します。
models.py内
from google.appengine.ext import db class ToDoItem(db.Model): owner = db.UserProperty(required=True) title = db.StringProperty(required=True) detail = db.TextProperty() reg_date = db.DateTimeProperty(auto_now_add=True) deadline = db.DateTimeProperty(required=True)
GAEp のデータストアに格納するために、Model クラスを継承します。このクラスは、google.appengine.ext.db パッケージに格納されています。
ToDoItem クラスには、5つのプロパティが定義されています。
- owner
- ひとつ ToDo アイテムの所有者。必須
- title
- ToDo 内容。通常ここに何をすべきかを記載する。必須
- detail
- ToDo 内容の詳細。
- reg_date
- この ToDo アイテムの登録日
- deadline
- この ToDo アイテムの締め切り。必須
各データ項目は、Property クラスを継承した各クラスで定義しています。どのようなプロパティが GAEp で定義されているかは下記で確かめられます。
また、Property のコンストラクタに required 引数と auto_now_add 引数を使用しています。
required 引数は Properyty クラスのコンストラクタ引数です。これによりプロパティに None を入れるとエラーが返ります。他にもコンストラクタ引数があります。下記参照。
auto_now_add 引数は DateTimeProperty クラス固有のプロパティで、インスタンス作成時にその時点の時刻を自動で代入します。下記を参照してください。
deadline については、仕様的には DateProperty でも充分です。
モデルインスタンスの作成、変更、保存、削除
上記のように作成したモデルのインスタンス(エンティティ)のライフサイクルに関する操作を簡単に記載します。
エンティティの作成は、以下のようにします。
item = ToDoItem(owner=user, title=s_title, deadline=dt_deadline)
required なプロパティはコンストラクタ引数で初期化しています。これらを初期化しなければ、エラーとなります。
item = ToDoItem() # 必須なプロパティが初期化されていないのでエラー
コンストラクタ引数なしでエンティティ作成したい場合は、プロパティのコンストラクタ引数に default を None 以外の値で指定しておく
変更は以下のようにします。
item.detail = 'この ToDo アイテムの詳細はこれこれです'
required なプロパティには、None を代入できない点にだけ注意。
変更したら、保存は以下のようにします。
item.put()
コンストラクタで作成しただけではデータは保存されていません。保存は必ず put() メソッドで。
最後に、いらなくなったエンティティの削除は以下です。
item.delete()
今回はここまで。拍子抜けするくらい簡単です。
参考
Google App Engine については、基本的に Google が公開しているデベロッパーガイドを見ればだいたいのことはわかります。内容もわかりやすいです。
特に、Google App Engine Python については、以下です。
- http://code.google.com/intl/ja/appengine/docs/python/gettingstarted/
- http://code.google.com/intl/ja/appengine/docs/python/overview.html
基本的にはこれらのサイトを見ればほとんどのことはわかりますが、その他に僕は以下の本を参考にしています。
- 作者: Dan Sanderson
- 出版社/メーカー: Oreilly & Associates Inc
- 発売日: 2009/11/15
- メディア: ペーパーバック
- クリック: 29回
- この商品を含むブログ (6件) を見る
和訳も出ているようです。
- 作者: Dan Sanderson,玉川竜司
- 出版社/メーカー: オライリージャパン
- 発売日: 2011/01/24
- メディア: 大型本
- 購入: 5人 クリック: 414回
- この商品を含むブログ (27件) を見る
GAEpでiPhone向けWebアプリを作る (4)GAEpプロジェクトとそのファイル構成
前回の続きです。
GAEpプロジェクトとそのファイル構成
Google App Engine Pythonプロジェクトの作成
プロジェクト作成方法は、スタートガイドあたりを参考に適当に。ここでは割愛。
プロジェクト内のファイル構成
以下のようなファイル構成にしました。
<project dir>/ +--app.yaml +--index.yaml +--cron.yaml +--main.py +--todo/ +--__init__.py +--handlers.py # RequestHandlerクラス群 +--models.py # DataStoreクラス群 +--tasks.py # cronタスククラス群 | +--staticdir/ # 静的ファイル格納 | +--views.html # メインビュー | +--bye.html | +--todo.manifest # 現在未使用 | +--css/ # css格納 | | +--iphone.css | | +--todo.css | +--js/ # javascript格納 | | +--jquery-1.4.4.min.js | | +--default.js | +--img/ # 画像リソース格納 | +--button.png | +--back_button.png | +--templates/ # テンプレートファイル格納 +--views.tpl@
今回作ってみて、この構成に対して以下の感想を持っています。
- 静的ファイルstaticdir/とテンプレートファイルtemplates/は明確に分けるべき
- staticdir/を設けることでpythonスクリプトと静的ファイルを明確に分離できる
- staticdir/内には実際のサービス時と同一の相対パスで html/css/javascript を配置
- staticdir/の中で html/css/javascript のデバッグがしやすい
- 本当は、静的ファイル群(staticdir/)とスクリプト(*.pyやテンプレートファイル群)は同一のディレクトリ階層に配置するのはあまりよくないかもしれない。が、近いほうが安心するので今回はこのようにした
なお、特に静的ファイルとテンプレートファイルの混同には、充分注意すべきです。同一パスのファイルを静的ファイルとしてもテンプレートファイルとしても利用するのは GAEp 上禁止されています。GAEp アプリは、サーバにアップロードされる際、静的ファイルは StaticFileServer に、テンプレートファイルは ApplicationServer にアップロードされるようです。つまりアップロード先が異なります。
どうしても静的ファイルとテンプレートファイルを同一にしたい場合には、シンボリックリンクを作成します。例えば、上記のファイル構成図で、templates/views.tpl ファイルは、staticdir/views.html ファイルのシンボリックリンクにしてあります。このようにしておくと開発機上では実体ファイルをひとつにしつつ、アップロード時に両方のサーバにアップロードされます。
app.yamlの記述 (ユーザ認証なし)
app.yaml の内容を下に示します。ただし、この段階ではまだユーザ認証は設定していません。
app.yaml内
application: penguinwatcher version: 1 runtime: python api_version: 1 builtins: - remote_api: on handlers: - url: /todo/js static_dir: todo/staticdir/js - url: /todo/css static_dir: todo/staticdir/css - url: /todo/img static_dir: todo/staticdir/img - url: /todo/(.*\.html) static_files: todo/staticdir/\1 upload: todo/staticdir/(.*\.html) - url: /todo/tasks/.* script: main.py login: admin - url: /todo/.* script: main.py
js/, css/, img/, *.htmlは、todo/直下のパスにマッピングすることにします。
つまり、
(URL) http://penguinwatcher.appspot.com/todo/views.html ↓ (ファイルパス) ./todo/staticdir/views.html
また、同様に、todo/直下のパスに リクエストハンドラをマッピングします。
本日はここまで。次回はモデル(models.py)およびリクエストハンドラ(handlers.py)を書いていきます。
参考
Google App Engine については、基本的に Google が公開しているデベロッパーガイドを見ればだいたいのことはわかります。内容もわかりやすいです。
特に、Google App Engine Python については、以下です。
- http://code.google.com/intl/ja/appengine/docs/python/gettingstarted/
- http://code.google.com/intl/ja/appengine/docs/python/overview.html
基本的にはこれらのサイトを見ればほとんどのことはわかりますが、その他に僕は以下の本を参考にしています。
- 作者: Dan Sanderson
- 出版社/メーカー: Oreilly & Associates Inc
- 発売日: 2009/11/15
- メディア: ペーパーバック
- クリック: 29回
- この商品を含むブログ (6件) を見る
和訳も出ているようです。
- 作者: Dan Sanderson,玉川竜司
- 出版社/メーカー: オライリージャパン
- 発売日: 2011/01/24
- メディア: 大型本
- 購入: 5人 クリック: 414回
- この商品を含むブログ (27件) を見る
GAEpでiPhone向けWebアプリを作る (3)アーキテクチャについて
時間があきましたが、前回の続きです。
アーキテクチャについて
アーキテクチャと呼ぶほどたいしたものではないですが、概要を説明しておきます。
構成の概要とシーケンス
下図のようにしています。
- まずユーザが、URLからビューとなるHTMLファイルをリクエスト。
- HTMLファイルがブラウザにロードされる。
- 同時にHTMLファイル内に指定されているcssファイルとjavascriptファイルもブラウザにロードされる。
- この時点で、ビューとコントローラはすべてブラウザにロードされます
- javascript からサーバにデータをリクエスト
- ToDo のデータがJSON形式でサーバからブラウザにロードされる
- javascript で、ロードされたJSONデータをHTMLにバインドする
構成の特徴
以下のような特徴でコーディングするよう自分に制限を課しました。
- ビューは html/css のみ
- html/css には純粋にビューのレイアウト情報だけ定義します
- モデルとして、サーバサイドに WebAPI を定義
- GAEp の RequestHandler として簡単な WebAPI を定義します
- モデルは JSON 形式でサーバからブラウザに送信します
- コントローラは javascript のみ
- ビューのコントロールはすべて javascript で実現します
- サーバサイドでビューとモデルを結合することをしません
- つまり、テンプレートエンジンでのビューとモデルの結合をやめます
- ビューとモデルの結合は jquery で実現します
これにより以下のような効果を期待をします。
- ブラウザ上にロードされた html/css/javascript の塊は、ブラウザ上で動作するクライアントアプリとしての役割を果たす。
- クライアントコンポーネントの html/css/javascript は、最初にすべてブラウザにロードしておく。これによりビューの操作感が向上する
- つまり、クリックするたびの html/css 読み込みによる遅延を抑制する(JSON データのロード遅延のみ)
- これにより、ビューの柔軟性を高める。
今回は以上です。
備忘:次回は GAEp プロジェクトとそのファイル構成についての予定。
GAEpでiPhone向けWebアプリを作る (2)iPhoneっぽくなるスタイルシートを書く
前回の続きです。
iPhoneっぽくなるスタイルシートを書く
ネイティブアプリのように見せる部品ごとのスタイルシートを書いていきます。
以下を説明します。
- NavigationBar のように見せる部品スタイル設定
- BarButtonItem のように見せる部品スタイル設定
- TableView のように見せる部品スタイル設定
テスト用 html を用意する
特徴は以下です。
- ナビゲーションバーがある(最上部のタイトルを表示した領域)
- ナビゲーションバーにはボタンが配置できる
- ナビゲーションバーには"戻る"ボタンも配置できる。
- 一覧をリスト状に表示できる
テスト用に以下のような html ファイルを作成します。
test.html
<html > <head> <title>ToDo list</title> <meta name="apple-mobile-web-app-capable" content="yes" /> <meta name="apple-mobile-web-app-status-bar-style" content="black" /> <meta name="viewport" content="user-scalable=no, width=device-width" /> <link rel="stylesheet" href="css/iphone.css" type="text/css" media="screen" /> <link rel="stylesheet" href="css/todo.css" type="text/css" media="screen" /> </head> <body > <div id="list" > <div class="navBar"> <h1 ><a href="#">Here is title</a></h1> <a class="barButton right" href="#">Next</a> <a class="barButton back" href="#">Back</a> </div> <ul > <li > <a href="#">List item 1</a> </li> <li > <a href="#">List item 2</a> </li> <li > <a href="#">List item 3</a> </li> </ul> </div> </body> </html>
paddingとmarginをゼロに
paddingとmarginはどうせ各部品で細かく調整設定します。なのではじめからゼロにしておきます。
ついでに全体のフォントは設定しておきます。
* { margin: 0; padding: 0; } body { font-family: Helavetica; font-size: 14px; }
iPhone で見ると次のようになります。
NavigationBar のように見せる部品スタイル設定
次にナビゲーションバーのスタイルを設定します。test.html 内の navBar クラスを指定した div タグへのスタイル指定です。
.navBar { background-color: #ccc; background-image: -webkit-gradient(linear, left top, left bottom, from(#ccc), to(#999)); border-color: #666 border-style: solid; border-width: 0 0 1px 0; } .navBar h1, h1 a{ color: #222; font-size: 20px; font-weight: bold margin: 0 auto; padding: 10px 0; text-align: center; text-shadow: 0px 1px 0px #fff; }
ポイントは、以下といったところです。
- .navBar で background-image にてグラデーション指定
- .navBar h1 にて
- font-weight でボールド
- text-align でセンター寄せ
- text-shadow で白色影
iPhone で見ると次のようになります。
BarButtonItem のように見せる部品スタイル設定
続いて、ナビゲーションバー上の BarButtonItem 状の部品のスタイル指定を行います。test.html 内の barButton クラスを指定した a タグへのスタイル指定です。
barButton では、ふたつのクラスを指定することでボタンを表現します。
- a class="barButton right" : ナビゲーションバー上の右端ボタン
- a class="barButton left" : ナビゲーションバー上の左端ボタン
- a class="barButton back" : ナビゲーションバー上の左端戻るボタン
.navBar .barButton { position: absolute; top: 7px; max-width: 64px; overflow: hidden; text-align: center; line-height: 28px; text-overflow: ellipsis; text-decoration: none; border-width: 0 5px; padding: 0 3px; color: #fff; text-shadow: rgba(0,0,0,0.6) 0px -1px 0px; -webkit-border-image: url(../img/button.png) 0 5 0 5; } .navBar .barButton.back { border-width: 0 8px 0 14px; -webkit-border-image: url(../img/back_button.png) 0 8 0 14; }
主な注意点は以下。
- position は absolute
- max-width と text-overflow でテキストが入り切らなかったときの対策
- webkit-border-image で別途用意したボタンの画像と戻るボタンの画像を指定
- 戻るボタンの場合、左右の幅指定を別にしていることに注意
続いて、ボタンを左右に指定する補助クラスを定義しておきます。
.right { right: 6px; } .left { left: 6px; } .back { left: 6px; }
これで iPhone で見ると次のようになります。
TableView のように見せる部品スタイル設定
続いて、UITableView のように見せる部品スタイルを設定していきます。
UITableView には、UITableViewStylePlain と UITableViewStyleGrouped のふたつのスタイルがありますが、今回設定するのは UITableViewStyleGrouped の方にします。
まずは、ul タグを以下のように設定します。ul のアイテムの項目マークをなしにし、margin を指定しておきます。
ul { list-style: none; margin: 10px; padding: 0; }
次にリスト項目の設定です。
ul li a { background-color: #ffffff; border: 1px solid #999999; color: #222222; display: block; font-size: 17px; font-weight: bold; margin-bottom: -1px; padding: 12px 10px; text-decoration: none; }
ここで注意すべき内容は、以下です。
- display: block; でブロック表示指定
- text-decoration: none; でリンク下線は消しておく
また、UITableViewStyleGrouped の場合、リスト項目の1番目の項目の左上と右上の角、および、リスト項目の最後の項目の左下と右下の角、が丸くなっています。これを以下のように指定します。
ul li:first-child a { -webkit-border-top-left-radius: 8px; -webkit-border-top-right-radius: 8px; } ul li:last-child a{ -webkit-border-bottom-left-radius: 8px; -webkit-border-bottom-right-radius: 8px; }
最後に一応 a:active と a:hover に空指定をしておきます。
iphone.css内
ul li a:active, ul li a:hover { }
これで iPhone で見ると次のようになります。
以上で、今回作成したい画面のおおよそのスタイルは設定を終えます。色や画像の変更は todo.css ファイルでオーバーライドすることにします。
参考
今回の記事の内容は、次の本の内容を参考にカスタマイズしています。
iPhoneアプリケーション開発ガイド ―HTML+CSS+JavaScript による開発手法
- 作者: Jonathan Stark,増井俊之,牧野聡
- 出版社/メーカー: オライリージャパン
- 発売日: 2010/08/07
- メディア: 大型本
- 購入: 20人 クリック: 593回
- この商品を含むブログ (47件) を見る
GAEpでiPhone向けWebアプリを作る (1)全体的な見た目を作る
前回の続きです。
ネイティブアプリのように見せる全体的な設定
次の内容を説明します。
- 表示領域の固定
- ブラウザのアドレスバーとツールバーを消す設定
- ステータスバーの色を変更する設定
html ファイルの head タグでは、5つの指定をします。
表示領域の固定
ページ幅を固定するために以下の指定をします。
html ファイルの head タグ内
<meta name="viewport" content="user-scalable=no, width=device-width" />
これにより、iPhone でのページ表示時に、ピンチイン/ピンチアウトでコンテンツの拡大/縮小されるのを防止します。
ブラウザのアドレスバーとツールバーを消す設定
Webアプリは通常ブラウザ内に表示されます。従って、ブラウザのアドレスバーとツールバーが表示され、その内側の領域にコンテンツが表示されます。
しかし下記の設定を行うことで、アイコンから起動したときに限ってですが、アドレスバーとツールバーを非表示にすることができます。
html ファイルの head タグ内
<meta name="apple-mobile-web-app-capable" content="yes" />
iPhoneのブラウザから表示すると次の図のように表示されます。
しかし、上記 meta タグの設定された状態で、このページをホーム画面にブックマークします。
そしてiPhone のホーム画面に追加されたアイコンからこのページを開くと以下のようにアドレスバーとツールバーが消えます。
これで、アイコンからWebアプリを立ち上げるとネイティブアプリのような見た目となります。
ステータスバーの色の設定
Webアプリ表示時にiPhoneのステータスバーの見た目を変更することができます。ただし、これもアイコンから立ち上げたときの効果です。
以下のように設定します。
html ファイルの head タグ内
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
参考
今回の記事の内容は、下記の Apple 資料に記載されています。
また、次の本にも記述されています。
iPhoneアプリケーション開発ガイド ―HTML+CSS+JavaScript による開発手法
- 作者: Jonathan Stark,増井俊之,牧野聡
- 出版社/メーカー: オライリージャパン
- 発売日: 2010/08/07
- メディア: 大型本
- 購入: 20人 クリック: 593回
- この商品を含むブログ (47件) を見る
iPhone 向け Web サイトを作ろうと思っている方にはオススメです。
GAEpでiPhone向けWebアプリを作る (0)はじめに
はじめに
Google App Engine Python を使ったiPhone向けWebアプリを作ってみました。今後暇を見つけて、何回かにわけてこのブログにその内容を掲載したいと考えています。
iPhone向けアプリはたくさんありますが、たいていはiTunes App Storeに登録されているObjective-Cで書かれたネイティブアプリです。
一方、iPhone向けアプリにはもうひとつ、Webアプリというカテゴリがあります。こちらはApp Storeのようなポータルがないせいか(どこかにある?)あまり話題になることはありません。
iPhone向けWebアプリがどんなものかという個人的な興味で、ひとつ簡単なアプリを作ってみましたので、その内容をこのブログでログに残します。
それから Google App Engine (GAE) です。前にGAEpを使ってWebアプリをひとつ作ってみましたが、そのパワーを実感するためにもうちょっと実用的なアプリも作ってみようと思い、今回作業しました。その辺のノウハウの自分用備忘録もかねています。
iPhone向けWebアプリとは
- メリット
- iTunes App Storeに登録する必要がない
- 従って、Appleの審査もないし、年会費も必要ない
- Objective-Cもxcodeも必要ない。従ってMacを購入する必要もない
- HTML/CSS/javascriptで作れる
- ネイティブアプリに近い見た目を提供できる
- 特に、iPhoneのブラウザから「ホーム画面に追加」でiPhoneホーム画面にブックマークして立ち上げると、かなりネイティブアプリに近い使用感
何を作ったか
できるだけ簡単で、かつ実用性も高そうなアプリということで、ToDo管理アプリを作ってみることにしました。こんな感じです。
見た目がネイティブアプリにそこそこ近いのはわかるかと思います。
以下より実際に触ってみることができます。ただし、google IDによるログインが必要です。
http://penguinwatcher.appspot.com/todo/main
iPhone/iPod touchまたはパソコン版Safariでご確認ください。特にiPhone/iPod touchをご利用の場合は、上記URLにアクセスした後、「ホーム画面に追加」でiPhone/iPod touchのホームにアイコンを追加し、続いてそのアイコンから立ち上げてみてください。
仕様は以下です。できるだけ簡単な仕様にしました。
- 認証を用いてToDo(やること)を個人別に管理できる
- ToDoを登録できる。登録には以下を設定できる。
- ToDoのタイトル(必須)
- ToDoの詳細(任意)
- ToDoの締め切り日付(必須)
- ToDoの一覧を閲覧できる
- 締め切りが近い20件
- 締め切り後一定の日にちが経過したToDoアイテムは、サーバ側で自動削除
- 登録済みのToDoの内容を閲覧および編集できる
- 登録済みのToDoの内容を削除できる
計画停電情報のコピペ
東電が繋がりにくいので、以下に情報コピペを残しておく。