体験記/Oracle Certified Expert, Java EE 6 Web Component Developer (1Z0-899) 資格取得
先日、Oracle Certified Expert, Java EE 6 Web Component Developer (1Z0-899)(以下、ocej-wcd と略記) を取得しました。
僕は日本語で受験しました。
この資格を持っている人はけっこういるのだと思いますが、意外と検索に引っかからなかったので、興味を持っている方のお役に立つかもと思い、体験を書いてみます。
(下に中途半端な連載がありますが無視して)
背景
資格取得前の僕自身の背景です。
結果
- 68% で合格
- 一度目で合格
勉強方針
個人的な意見として、資格はあまり取りたくないと考えています。資格のための勉強時間がもったいないと感じるのと、資格の成果をモノづくりに活かせてないと感じているからです。ただ今回は、仕事の成り行き上取らざるを得なかったので取りました。
というわけで、ギリギリでいいので最小限の時間で取得することを目標にしました。
読んだ書籍
ocej-wcd の日本語の書籍は、現時点(2014-08-25)で僕の知る限り一冊もありません。なので、以下のふたつをやってみました。
まずひとつめ。
SUN教科書 Webコンポーネントディベロッパ(SJC-WC)(試験番号:310-083)
- 作者: 山本道子
- 出版社/メーカー: 翔泳社
- 発売日: 2010/06/29
- メディア: 単行本(ソフトカバー)
- 購入: 4人 クリック: 23回
- この商品を含むブログ (10件) を見る
印象は以下。
- Java EE 5 用だが
- かなりよくまとまっている
- 解説があって、章末に問題があり、最後に模擬試験という形式
- 練習問題の難易度や雰囲気も本番に近い
- 2周やった
- 自分の弱い部分だけ手書きノートで抜き出した。20ページくらい
他の書籍を読んだことがないのですが、servlet/jspの参考書としても良い気がします。
ふたつめ。
徹底攻略Oracle認定Webコンポーネントディベロッパ EE 5問題集[CX-310-083]対応 (ITプロ/ITエンジニアのための徹底攻略)
- 作者: 米山学,株式会社ソキウス・ジャパン
- 出版社/メーカー: インプレス
- 発売日: 2011/01/21
- メディア: 単行本(ソフトカバー)
- クリック: 23回
- この商品を含むブログ (3件) を見る
- これもJava EE 5用
- この本はあまり良いとは思えない
- 問題の性質が本番とかけ離れている
- こちらの方は練習問題のみで、回答の解説の中で説明する形式
- 1周目の途中で時間のムダが大きいと判断して中断した
Java EE 6。Java EE 5ではない
受験3日前くらいまでは、Java EE 5の勉強だけでいけるだろうと楽観視していました。この時点で上記のひとつめの書籍で正答率は85%程度。しかしネット上の模擬試験を行うと、Java EE 5だけではやはり歯が立たないかもしれないと感じはじめました。
そのとき活用したのは以下です。情報源は Passed OCEJWCD 6 and share my experience (certification results forum at Coderanch) が役立ちます。ただしすべて英語です。
こちらは言わずもがなですが、なんだかんだで役立ちます。上記の情報源を元に以下を読みます。
2.3.3.3 Asynchronous processing 3.2 File upload 8 Annotations and pluggability 13.2 Declarative Security 15.5 Annotations and Resource Injection
ただ、全部読むのは時間がかかるので、はやめに模擬テストをしたいと考えました。
そこで以下が役立ちます。実際、仕様書を読むのを途中でやめてこれに移りました。
ここは簡易テストであれば無料で可能です。また\2,000程度でフルバージョンが入手できます。僕は購入しました。ウェブアプリ版もあるのでタブレットで手軽に学習できるのが良いところです。購入した価値はあったと感じます。ただし、問題難易度は本番より高めです。なので、本番想定の練習には微妙です。
受験本番
以下が受験本番に対する感想です。
以上
ご参考まで。
GAEpでiPhone向けWebアプリを作る (11)ビューデータバインダを書く
前回の続きです。
ビュー<->データバインダを書く
サーバから受け取ったデータを、html ビューにバインドする処理を、javascript を使って書いていきます。
この処理には、css と jquery の組み合わせは非常に有用です。java では jsp があったり、django にもテンプレート言語があったりしますが、jquery を使うのであれば、テンプレートエンジンはもう必要ないのではないかという気もしてしまいます。
メリットとしては以下です。
- html ファイルがそのままテンプレートファイル
- 特殊な文法のテンプレートを覚える必要がない
- html ファイルを開くだけで見た目がチェック可能
- 保守が楽。変更したいときにすぐに変更できる
- 通信はデータのみで済む。処理速度的メリット
- ビューとデータの結びつきが疎になる
もちろんデメリットもあると思います。
- css ベースの選択処理(id や class)がどうしてもグローバル変数的になる
- 同様に、ビュー・データ・バインダの結びつきもうまくまとめないとわかりにくい
- テンプレート継承が使えない
- javascript のコードが多くなる
今回はあまりできていませんが、以下あたりが今後の課題になってきます。
- html / css のモジュール化
- バインダがビューとデータを結びつけるフレームワーク
- javascript 処理の簡素化とデバッグ容易化
これらはどれも関連するように感じます。特に、html / css のモジュール化は非常に重要になってくるだろうなと感じます。
今回のコードの全体はこちらです。
グローバル変数
今回は、ふたつのグローバル変数を用意しています。
- ユーザ情報を格納する変数
- ToDo 項目のリストを格納する変数
どちらもビューの作成をやりやすくするために導入してます。特にグローバル変数に持っていなくても問題ないと思いますが、通信量は減りそうだと思って入れています。
js/default.js内
var context = { 'userinfo': {}, 'items': [] };
ユーザ情報のバインド
#list 画面にはユーザ情報を表示する箇所があります。
views.html の div#list タグ内
<div class="userinfo"> Welcome, <span class="user-nickname">guest</span>. (<a class="user-logout" href="/todo/main">logout</a>) </div>
jquery 的には最も単純な処理です。
js/default.js内
function setUserInfo(nickname, logoutUrl) { $('#list .userinfo .user-nickname').text(nickname); $('#list .userinfo a.user-logout').attr('href', logoutUrl); }
例えば以下では、div#list タグの下の div.userinfo タグの下の span.user-nickname タグにニックネーム文字列を挿入しています。
$('#list .userinfo .user-nickname').text(nickname);
ToDo 項目データを一覧でビューにバインド
次に、ToDo 項目のデータをリスト形式で表示します。
表示部の html は以下です。
views.html の div#list タグ内
<ul class="todoitem-list" > </ul> <ul class="todoitem-template" > <li class="todoitem" > <span class="todoitem-delete" >Delete</span> <a class="todoitem-anchor" href="#save"> <span class="todoitem-title">This is a todo item area.</span> <em class="todoitem-deadline">YYYY-MM-dd</em> </a> <div class="clear"> </li> </ul>
この処理は refreshItems() 関数で行っています。
js/default.js内
function refreshItems() { // (1) var $todoparent = $('#list ul.todoitem-list'); var $todoitemTpl = $('#list ul.todoitem-template li.todoitem:first'); $todoparent.find('li.todoitem').remove(); // 既存データを削除 // (2) for(var idx = 0; idx < context.items.length; idx += 1) { // (3) var $todoitem = $todoitemTpl.clone(); // テンプレートをコピー var data = context.items[idx]; $todoitem.find('.todoitem-title').text(data.title); $todoitem.find('.todoitem-deadline').text(data.deadline); $todoitem.find('.todoitem-anchor').attr('id', data.key); // 項目キー $todoitem.removeClass('hidden'); // (4) $todoitem.appendTo($todoparent); // 項目を追加 $todoitem.find('.todoitem-anchor').click(function(data) { // (5) ToDo 項目を選択されたら return function(e) { var item = data; setItemToSaveForm(item); // #save 画面にデータをバインド transitTo('#save'); // 画面遷移実行 return false; }; }(data)); $todoitem.find('.todoitem-delete').click(function(item) { // (6) 削除ボタンを押されたら return function(e) { var bDelete = confirm('Do you really delete it?'); if(bDelete) { deleteItem(item.key, function(data, ts, xhr) { if(ts === 'success') { loadItems(); } }); } return false; }; }(data)); } }
まずは、(1) で項目の挿入先($todoparent)と項目テンプレート($todoitemTpl)を取得し、挿入先を空にしてます。
それから、ループで(2)ひとつずつ ToDo 項目を追加していきます。
まずテンプレートのクローンを作成し(3)、グローバル変数内の項目をタグに割り当てます。この際、a タグに id を割り当てています。この id は、GAEp のモデルのキーです。これによってデータを識別します。
続いて(4)で、挿入先($todoparent)にいま作成したタグを追加します。
最後に、いま追加した項目に対してクリックハンドラを付けます。.todoitem-anchor タグには #save 画面への画面遷移、.todoitem-delete タグには ToDo 項目の削除処理を書いています。
ToDo 項目編集ビューにデータをバインド
最後、ToDo 項目編集ビュー (div#save 要素) にデータをバインドします。この処理は #list 画面からの画面遷移直前に呼ばれます(上記の(5))。
js/default.js内
function setItemToSaveForm(item) { if(item === undefined) { item = {'title':'', 'detail':'', 'deadline':'', 'key':''}; } var $saveForm = $('#save form.todo-ctrl'); $saveForm.find("input[name='todo-title']").attr('value', item.title); $saveForm.find("textarea[name='todo-detail']").text(item.detail); $saveForm.find("input[name='todo-deadline']").attr('value', item.deadline); $saveForm.find("input[name='todo-key']").attr('value', item.key); }
内容に特に難しい内容はありません。単純に input 系タグにデータを入れているだけです。
todo-key という名前を持った hidden タイプの input 要素に GAEp のモデルキーを持たせてデータの識別をしています。
item === undefined の場合は、新規作成です。
次回は、サーバとのデータ通信関数です。
参考
jquery の入門としては、以前にも紹介した次の本が非常によいと思います。
iPhoneアプリケーション開発ガイド ―HTML+CSS+JavaScript による開発手法
- 作者: Jonathan Stark,増井俊之,牧野聡
- 出版社/メーカー: オライリージャパン
- 発売日: 2010/08/07
- メディア: 大型本
- 購入: 20人 クリック: 593回
- この商品を含むブログ (47件) を見る
javascript に関しては、有名ですが、以下が間違いなくよい本です。
JavaScript: The Good Parts ―「良いパーツ」によるベストプラクティス
- 作者: Douglas Crockford,水野貴明
- 出版社/メーカー: オライリージャパン
- 発売日: 2008/12/22
- メディア: 大型本
- 購入: 94人 クリック: 1,643回
- この商品を含むブログ (190件) を見る
僕は仕事柄 javascript を使うことはほとんどありませんが、それでも、この本がその手の世界では必須の本であろうことは、なんとなくわかります。javascript が楽しい言語だと言うことがよくわかります。何より読んでて楽しいです。
GAEpでiPhone向けWebアプリを作る (10)各画面を書く
前回の続きです。
今回はビューの作成です。普段仕事で html/css を使う機会がないので、その奥深さに戦きます。
各画面を書く
続いて、各画面の html/css を書いていきます。今回の ToDo アプリでは画面がふたつ存在します。
- ToDo 一覧を表示する画面
- ひとつの ToDo 項目の編集画面
最終的な html は、こちら。css は todo.cssとiphone.css。
ToDo 一覧画面
この画面の html は以下の通りです。
views.html内
<div id="list" > <div class="navBar"> <h1 ><a href="main">ToDo list</a></h1> <a class="barButton right" href="#save">Add</a> </div> <div class="userinfo"> Welcome, <span class="user-nickname">guest</span>. (<a class="user-logout" href="/todo/main">logout</a>) </div> <ul class="todoitem-list" > </ul> <ul class="todoitem-template" > <li class="todoitem" > <span class="todoitem-delete" >Delete</span> <a class="todoitem-anchor" href="#save"> <span class="todoitem-title">This is a todo item area.</span> <em class="todoitem-deadline">YYYY-MM-dd</em> </a> <div class="clear"> </li> </ul> </div>
まずは、ナビゲーションバー部分です。
<div class="navBar"> <h1 ><a href="main">ToDo list</a></h1> <a class="barButton right" href="#save">Add</a> </div>
タイトルと右ボタンを配置しています。タイトルをクリックするとリロードします。右ボタンをクリックすると"#save"画面に遷移します。
次に、ユーザ情報の表示部です。ナビゲーションバーのすぐ下にログインユーザ名とログアウトのリンクを表示します。
<div class="userinfo"> Welcome, <span class="user-nickname">guest</span>. (<a class="user-logout" href="/todo/main">logout</a>) </div>
特に難しい部分はありません。ログアウトのアドレスは適当です。あとで jquery で正しい値を入れます。そのために span タグと a タグには jquery で処理する用のクラス名を指定しておきます。
それから、一覧表示部分です。
<ul class="todoitem-list" > </ul> <ul class="todoitem-template" > <li class="todoitem" > <span class="todoitem-delete" >Delete</span> <a class="todoitem-anchor" href="#save"> <span class="todoitem-title">This is a todo item area.</span> <em class="todoitem-deadline">YYYY-MM-dd</em> </a> <div class="clear"> </li> </ul>
この辺は少しトリッキーです。まず、実際の一覧表示部分は、"ul.todoitem-list" タグです。"ul.todoitem-template" タグには、リストアイテムのテンプレート "li.todoitem" を格納しています。
javascript で行う以下の処理を行う意図です。
- ToDo アイテムの個数分、ul.todoitem-template から li.todoitem タグをコピー
- Web API から得たデータを各 li.todoitem 内の要素にバインド
- ul.todoitem-list タグにその li.todoitem タグを挿入
"todoitem-template" クラスは css 内にて非表示にしてあります。
.todoitem-template { display: none; }
また、"li.todoitem" のレイアウトにはけっこう苦労しています。iOS SDK でいうところの、UITableViewCell の UITableViewCellStyleSubtitle のスタイルにボタンを追加したレイアウトを再現しようとしています。
- [Delete] ボタンを載せて、右に寄せる (float:right;)
- 要素全体は a タグで1要素全体でリンクの働きをするように
- 1要素内でタイトルと締め切り(deadline)の2行となるように
もっときれいな css の書き方があるかもしれない。
ToDo 編集画面
こちらは特に難しい部分はありません。
この画面の html は以下の通り。
views.html内
<div id="save" > <div class="navBar" > <h1>Edit ToDo</h1> <a class="barButton back" href="#list">Cancel</a> </div> <form method="post" class="todo-ctrl" action="/todo/savereq" > <ul> <li> <label>Title:</label> <input type="text" name="todo-title" /> </li> <li> <label>Deadline:</label> <input type="text" placeholder="YYYY-MM-dd" name="todo-deadline" /> </li> <li> <label>Detail:</label> <textarea name="todo-detail"></textarea> </li> <li> <input type="hidden" name="todo-key" value="" /> <input type="submit" value="Save" /> </li> </ul> </form> </div>
「戻る」ボタンがついたナビゲーションバーと、あとは単純なフォーム送信画面です。特にこれと言って特殊なことはしていません。
強いてあげるなら、css で label タグの幅を 100 % にして、入力部分を次の行に折り返しているくらいです。
これでビューの作成は終わり。次回から javascript です。
GAEpでiPhone向けWebアプリを作る (9)画面遷移の方法
前回の続きです。
もはや趣味では違うコードを書いているので、この記事のモチベーションを保つのが難しい。
画面遷移の方法
以前に書いた通り、このアプリのすべての主要な画面は、最初のアクセス時にすべてブラウザにロードするようにします。つまり、アプリ用の HTML ファイルは1枚のみです。
今回の ToDo アプリでは画面がふたつ存在します。
- ToDo 一覧を表示する画面
- ひとつの ToDo 項目の編集画面
これら複数の画面を javascript を用いてどのように画面遷移するか考える必要があります。今回はjqtouchを参考にしてそれを実現することにしています。
各画面を表す HTML
まず、以下のような1枚の html ファイルを作成します。
- body タグの直下に複数の div タグを作成
- このひとつひとつの div タグが、1画面を表す
- 各 div タグにはそれぞれ id 属性を付ける
- この id 属性が画面の名前を表す
<html > <head> <title>ToDo list</title> <!-- 略 ||--> </head> <body > <div id="list" > <!-- ToDo 一覧を表示する画面の HTML をここに書く --> </div> <div id="save" > <!-- ひとつの ToDo 項目の編集画面 の HTML をここに書く --> </div> <!-- : 他に画面が必要なら同様に並べる : --> </body> </html>
画面遷移はアンカーリンクで
アンカーリンクのクリックで別画面へ遷移するようにします。
例えば以下のような感じです。
<div id="list" > : <a href="#save">New</a> : </div>
上記の例は、一覧画面(list)内から新規作成画面(save)へ遷移するアンカーリンクを表します。
css/javascript による画面遷移処理
まず、css を準備します。
- css で、body タグ直下のタグはすべて display:none; にする。
- body タグ直下で有効な current という css クラスを用意し、これは display:block; にする。
つまり、以下のようにします。
todo.css内
body > * { display: none; position: absolute; left: 0; width: 100%; } body > .current { display: block; }
アプリロード時に(つまり、$(document).ready() で)、以下を行います。
- body タグ直下の一番上の タグに current クラスを付ける
- つまり、一番上の div タグだけ表示する。それ以外のタグは display:none; なので不可視。
- href の値が '#' ではじまるアンカーリンクはすべてハイジャックし、画面遷移関数を呼ぶようにする
画面遷移関数では以下の処理を行います。
- body タグ直下のすべてのタグの current クラスをすべて削除
- 引数で渡された id のタグに対して current クラスを追加
- これにより画面遷移関数の引数に指定された id のタグだけが可視になる
言葉ではわかりにくいのでコードを書きます。
todo.js内
$(document).ready(function() { init(); }); function init() { var currentPage = undefined; // body タグ直下の一番上の タグに current クラスを付ける if($('body > .current').length === 0) { currentPage = $('body > *:first'); } else { currentPage = $('body > .current:first'); $('body > .current').removeClass('current'); } $(currentPage).addClass('current'); scrollTo(0, 0); // href の値が '#' ではじまるアンカーリンクはすべてハイジャックし、 // 画面遷移関数を呼ぶようにする $("a[href^='#']").unbind('click'); $("a[href^='#']").click(function(e) { e.preventDefault(); transitTo($(this).attr('href')); }); // : // : } // 画面遷移関数 function transitTo(viewid) { var next = $('body > ' + viewid + ':first'); if(next) { // body タグ直下のすべてのタグの current クラスをすべて削除 $('body > .current').removeClass('current'); // +引数で渡された id のタグに対して current クラスを追加 var currentPage = next; $(currentPage).addClass('current'); } }
これで画面遷移の用意ができました。
参考
今回はあえて使用していませんが、普通に iphone 向け Web アプリを作りたいならば、jqtouch を使うと楽です。オススメです。
GAEpでiPhone向けWebアプリを作る (8)続・リクエストハンドラをを実装していく
前回の続きです。
実装は簡単なのに話しが長くなってきて、いつまで続くのか不安です。
今回ここで作ったToDo アプリは、スケッチ用に作ってみたものですが、よくよく見回してみると ToDo アプリはけっこうあるもんです。Gmail も ToDo を管理する用途の機能を持ってるようですし、こないだ発表されたiOS5 でも Reminders と呼ばれる高機能な ToDo 管理アプリが入るようです。
GAEp 上にリクエストハンドラを定義する
前回長くなってやめた残りのふたつを実装していきます。
SaveHandler の実装
SaveHandler では、以下のふたつの仕事をします。
- ToDoアイテムの新規作成
- 既存のToDoアイテムの編集
todo/handlers.py内
import datetime, time import logging from google.appengine.ext import webapp from google.appengine.ext import db from google.appengine.api import users from todo.models import ToDoItem # 〜〜〜 # class SaveHandler(webapp.RequestHandler): # def post(self): logging.debug('SaveHandler#post') user = users.get_current_user() if user: req = self.request itemkey = req.get('todo-key') s_title = req.get('todo-title') s_detail = req.get('todo-detail') s_deadline = req.get('todo-deadline') dt_deadline = datetime.datetime.strptime(s_deadline, '%Y-%m-%d') item = None if(len(itemkey) != 0): item = db.Model.get(itemkey) item.title = s_title item.detail = s_detail item.deadline = dt_deadline; else: item = ToDoItem( owner=user, title=s_title, detail=s_detail, deadline=dt_deadline, ) item.put() return
ユーザがログイン済みかどうかの処理は前回と同じです。
まず、入力の取得。
req = self.request itemkey = req.get('todo-key') s_title = req.get('todo-title') s_detail = req.get('todo-detail') s_deadline = req.get('todo-deadline') dt_deadline = datetime.datetime.strptime(s_deadline, '%Y-%m-%d')
入力は、RequestHandler の request フィールドから get() メソッドで取ることができます。
deadline だけは文字列(YYYY-mm-dd形式)から datetime インスタンスに変換しています。
multipart/form-data がこんなにも簡単に取得できるのは素晴らしいと言うに尽きます。
リクエストが、編集なのか新規作成なのかは、todo-key があるか否かで判別しています。
todo-key がある場合は編集。
item = db.Model.get(itemkey) item.title = s_title item.detail = s_detail item.deadline = dt_deadline;
編集の場合は、キーを元にデータストアから既存のレコード(エンティティ)を取得し、各プロパティに新しい値を代入しています。
todo-key がない場合は新規作成。
item = ToDoItem( owner=user, title=s_title, detail=s_detail, deadline=dt_deadline, )
ToDoItem エンティティをコンストラクタで新規作成しています。
で、最後にコミット。
item.put()
DeletionHandler の実装
最後に DeletionHandler 。ここでは既にある ToDo アイテムを削除します。
todo/handlers.py内
import logging from google.appengine.ext import webapp from google.appengine.ext import db # 〜〜〜 # class DeletionHandler(webapp.RequestHandler): # def post(self): logging.debug('DeletionHandler#post') itemkey = self.request.get('todo-key') item = db.Model.get(itemkey) if(item != None): item.delete() return
特に難しい部分はないです。
todo-key で削除対象のエンティティのキーを取得し、それを削除します。
ここまででサーバサイドの python コードは完了。
次からはクライアントサイドを書いていきます。
参考
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アプリを作る (7)リクエストハンドラをを実装していく
前回の続きです。
リクエストハンドラを実装していく
続いて、GAEp のリクエストハンドラを実装していきます。
各実装ごとに部分的に書いていきます。
MainView の実装
MainView#get() では、単純に html を出力します。
todo/handlers.py内
import os from google.appengine.ext.webapp import template # 中略 # class MainView(webapp.RequestHandler): # def get(self): s_tplpath = 'templates/views.tpl' path = os.path.join(os.path.dirname(__file__), s_tplpath) self.response.out.write(template.render(path, {}))
- templates/views.tpl という名称のテンプレートファイルを http レスポンスとして出力しています。
- テンプレートファイルと言いつつ、実はテンプレートではなく、html ファイルそのものです。データを埋め込みません。render() メソッドの第2引数は空オブジェクトです。
- templates/views.tpl は、staticdir/views.html のシンボリックリンクになっています。
- staticdir/views.html には、すべてのビューが含まれています。これは次回以降に。
GAEp のテンプレートエンジンは、デフォルトでは django のテンプレートエンジンとなっています。django のテンプレートエンジンのリファレンスは以下。
サーバサイドのテンプレートエンジンを利用したビューとモデルのバインディングはそれはそれでパワフルですが、今回はバインディングはクライアントサイドの javascript で行います。なので、ここで返すのは静的ファイルのみです。
ToDoList の実装
続いて、ToDoList#get() の実装です。
todo/handlers.py内
import logging from google.appengine.ext import webapp from google.appengine.api import users from django.utils import simplejson as json from todo.models import ToDoItem # 〜〜〜 # class ToDoList(webapp.RequestHandler): # def get(self): logging.debug('ToDoList#get') data = None user = users.get_current_user() if user: userinfo = { 'nickname': user.nickname(), 'logout_url': users.create_logout_url('/todo/bye.html') } q = ToDoItem.all() q.filter('owner =', user) q.order('deadline') results = q.fetch(20) itemlist = [{ 'key':str(item.key()), 'title':item.title, 'detail':item.detail, 'deadline':item.deadline.strftime('%Y-%m-%d'), } for item in results] data = { 'userinfo': userinfo, 'items': itemlist, } self.response.content_type = 'application/json' json.dump(data, self.response.out, ensure_ascii=False) return
import 文は、この部分に必要なものだけ書いています。
処理の流れは以下です。
- アクセスしている人がログイン済み(user != None)だったら、
- そのユーザの20件の ToDo アイテムを古いものから検索し、レスポンス用オブジェクト(itemlist)に変換し、
- ToDo アイテム(itemlist)とユーザ情報(userinfo)をひとまとめ(data)にして
- JSON データとして http レスポンスに出力
アクセスしている人がログイン済みのユーザかどうかは、User クラスのインスタンスを取得することで確認できます。
user = users.get_current_user() if user: userinfo = { 'nickname': user.nickname(), 'logout_url': users.create_logout_url('/todo/bye.html') }
取得は、google.appengine.api.users パッケージの get_current_user() 関数で行います。
リファレンスは以下です。
user != None ならログイン済み、そうでなければログインしていません。
また、ログアウト URL は、同じパッケージの create_logout_url() 関数で作成できます。この URL にアクセスすることで、ユーザはログアウトできます。引数には、ログアウト後のリダイレクト先 URL を指定できます。
以下の部分で、ユーザの ToDo アイテムを締め切りの古いものから20件検索しています。
q = ToDoItem.all() q.filter('owner =', user) q.order('deadline') results = q.fetch(20)
で、検索結果をレスポンス用オブジェクト(itemlist)に変換しています。
itemlist = [{ 'key':str(item.key()), 'title':item.title, 'detail':item.detail, 'deadline':item.deadline.strftime('%Y-%m-%d'), } for item in results]
itemlist はディクショナリオブジェクトのリストです。ひとつの ToDo アイテムは、ひとつのディクショナリオブジェクトで表し、以下を持っています。
- key
- ToDo アイテムのキー。これには、ToDoItem エンティティのキーをそのまま利用する。
- title
- ToDoItem エンティティの title プロパティ(ToDo タイトル)の値
- detail
- ToDoItem エンティティの detail プロパティ(ToDo 内容詳細)の値
- deadline
- ToDoItem エンティティの deadline プロパティ(この ToDo の締め切り)の値。"2011-06-05" のように"年-月-日" という書式で。
で、最後に、ユーザ情報(userinfo)と ToDo アイテムのレスポンス用オブジェクト(itemlist)をひとつのオブジェクト(data)にまとめ、JSON 形式で http レスポンスに書き出しています。
data = { 'userinfo': userinfo, 'items': itemlist, } self.response.content_type = 'application/json' json.dump(data, self.response.out, ensure_ascii=False)
GAEp には simplejson が入っているので、それを利用しています。ちょー簡単です。
長くなったので今回はここまで。
参考
Google App Engine については、基本的に Google が公開しているデベロッパーガイドを見ればだいたいのことはわかります。内容もわかりやすいです。
- 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アプリを作る (6)GAEp 上にリクエストハンドラを定義する
前回の続きです。
GAEp 上にリクエストハンドラを定義する
続いて、リクエストハンドラを定義していきます。
今回は、4つのリクエストハンドラを定義します。各リクエストハンドラの用途は以下です。
今回は実装しません。API だけ用意します。
リクエストハンドラのテンプレート作成
以下のようにします。
todo/handlers.py内
import logging from google.appengine.ext import webapp # class MainView(webapp.RequestHandler): # def get(self): pass # class ToDoList(webapp.RequestHandler): # def get(self): logging.debug('ToDoList#get') return # class SaveHandler(webapp.RequestHandler): # def post(self): logging.debug('SaveHandler#post') return # class DeletionHandler(webapp.RequestHandler): # def post(self): logging.debug('DeletionHandler#post') return
各リクエストハンドラは、RequestHandler クラスのサブクラスで定義します。リファレンスは以下です。
各リクエストハンドラの役割は以下です。
- MainView
- ビューの取得用。ここにアクセスされるとメインとなるビューを html で返す。アクセスポイント
- ToDoList
- ToDo アイテムのリスト取得 API。このハンドラにアクセスしたユーザの最近の20個の ToDo アイテムをリストで返す。GET メソッドのみサポート
- SaveHandler
- 特定のユーザの特定の ToDo アイテムの作成または変更を行う API。POST メソッドのみサポート。
- DeletionHandler
- 特定の ToDo アイテムの削除を行う API。POST メソッドのみサポート。
それぞれ特に難しい部分はありません。
リクエストハンドラの URL マッピング
上記の各リクエストハンドラを、URL マッピングしておきます。
main.py内
import logging from todo.handlers import MainView from todo.handlers import ToDoList, SaveHandler, DeletionHandler from google.appengine.ext import webapp from google.appengine.ext.webapp.util import run_wsgi_app application = webapp.WSGIApplication( [ ('/todo/main', MainView), ('/todo/list', ToDoList), ('/todo/savereq', SaveHandler), ('/todo/deletereq', DeletionHandler), ], debug=True) def main(): run_wsgi_app(application) if __name__ == "__main__": main()
WSGIApplication クラスのコンストラクタで URL マッピングを行います。エイリアスとリクエストハンドラの組み合わせをタプルで結びつけたリストを教えるだけ。
レファレンスは以下です。
参考
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件) を見る