検索
連載

Google App Engineで作るライフログこれ、俺ならこう使う(4)(2/2 ページ)

日々生み出されるネットサービスやテクノロジーに詳しい著者による、こんなふうにサービスに取り込んだら面白いのではないか、という提案。技術的な応用面にフォーカスしていく(編集部)

Share
Tweet
LINE
Hatena
前のページへ |       

今回作るもの:「logme」=次世代版「音ログ」

 logmeは、自分が聴いた音楽・読んだ本・見た映画を淡々と記録するWebサービスです。ほかのユーザーと情報を共有しコメントによるコミュニケーションを行うことで、新しい音楽・本・映像体験を生み出すことを目指します。

 僕は以前「音ログ」というサービスを開発していました。iTunesで聴いた音楽のタイトルをサーバにアップロードして履歴を残せるというものでしたが、iTunesの情報を取得するために専用のクライアントソフトウェアが必要で、もっと手軽に履歴を残したいという要望を多くのユーザーからいただいていました。

 logmeは、ブラウザのUIから手動で操作する音ログともいえるサービスで、対象となるメディアを拡張し、クライアントソフトウェアを不要にすることで、幅広いユーザーに使ってもらえることを目指しています。

サービスの概要

  • logmeはAmazonと連携した、音楽・書籍・DVDなどのデータベースを持っている。
  • ユーザーは、自分が読んだ書籍や聴いた音楽をlogmeのデータベースから検索して、簡単なコメントとともに「購入した」「読んだ」「聴いた」「見た」などの履歴を残すことができる。
  • ユーザーが残した履歴は、ユーザーページに一覧表示される。
  • ユーザーは、ほかのユーザーが残した履歴にコメントすることができる。
  • ほかのユーザーを「フォロー」することで、さまざまなユーザーの履歴の更新をまとめてチェックできる。
  • 履歴は、あらかじめ登録されたアカウント情報を基に、Twitterのつぶやきとしてポストすることもできる。

画面構成

  • トップ
  • 商品データベース
  • 一覧
  • 商品詳細
  • ユーザー
  • プロフィール一覧
  • プロフィール詳細
  • ログインページ
  • ログ
  • ログ一覧
  • ログ詳細
  • Myページ(ほかのユーザーからの更新情報をまとめて読む)

データ設計

  • 商品データベース
  • ユーザー
  • アクティビティ・ログ
  • そのほか

GAEを使ったサービス開発の実際

 上記の大まかな構成案を基に、GAEを使ってサービスを開発していきます。

 まずは、アプリケーションプロジェクトの置き場所として、適当な名前でディレクトリを作成します(ここではlogme)。以降、すべてのディレクトリ/ファイルはこのディレクトリの下に配置される前提でお読みください。

構成ファイルapp.yamlの作成

 

GAEにアプリケーションの基本情報を伝えるための構成ファイル、app.yamlを作成します。内容は下記のようになります。

application: logme
version: 1
runtime: python
api_version: 1
handlers:
- url: /
  script: index.py
- url: /.*
  script: not_found.py

 applicationに自分のアプリケーションIDをセットします。handlersでURLとハンドラが記述されたファイルのマッピングを行います。

 app.yamlの詳細な説明はGAEデベロッパーサイトの“アプリの構成”を参照してください。 app.yamlをはじめとするGAEの設定ファイルは、YAMLで記述します。YAMLについては“The Official YAML Web Site”をご覧ください。

ハンドラスクリプト

 上記app.yamlからサイトトップのページを処理するindex.pyはこんな構成になります。

from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
class Index(webapp.RequestHandler):
  def get(self):
    self.response.headers['Content-Type'] = 'text/plain'
    self.response.out.write('Welcome to logme!')
application = webapp.WSGIApplication(
                                     [('/', Index)],
                                     debug=True)
def main():
  run_wsgi_app(application)
if __name__ == "__main__":
  main()

 モジュールwebappをインポートして、webapp.RequestHandlerを継承するハンドラクラスIndexを定義しています。

 WSGIApplicationクラスを実体化する際に、このハンドラとURLのペアを初期化パラメータとして渡しています。これにより、index.pyが実行された際にURLと対応したハンドラが実行されます。

アプリケーションの実行

 ここまでできた時点で、アプリケーションを実行してみましょう。Mac OS XのGoogle App Engine Launcherでは「Run」ボタンを押すだけで、専用のWebサーバが起動してブラウザからアプリケーションにアクセス可能になります(Windows/Linuxではコマンドラインからスクリプトを実行する必要があります)。

ローカルホストのポート8081でアプリケーションにアクセス
ローカルホストのポート8081でアプリケーションにアクセス

 GAEのSDKは本番環境と同じアプリケーションの実行環境をエミュレートしていて、ユーザー認証などを含めてローカルでの動作チェックが可能になっています。

 Ruby on Railsなどと同様に、ローカル環境のセットアップが不要ですぐチェックできるので、開発者にとって作業しやすくなっています。

アプリケーションのデプロイ

 ローカル環境でテストを行った後は、アプリケーションのデプロイを行います。これによって、開発したアプリケーションがGAEのドメインで実際に公開されるようになります。

 従来、アプリケーションのデプロイは本番サーバのセットアップや構成ファイルのアップロードなど面倒で気を使うものでしたが、GAEではボタン操作のみ(Windows/Linuxではコマンドライン操作)でアップロードが完了し、そのほかには何もしなくても最新のコードを使ってサービスが行えます。

 デプロイが完了すると、URL“http://アプリケーションID.appspot.com/”で実際にアプリケーションにアクセスできるようになります(ドメインに関しては、後から独自ドメインを使用するように変更することもできます)。

ユーザー認証

 Users APIを利用することで、現在サービスにアクセスしているユーザーの情報を管理することができます。認証情報にはGoogleアカウントの登録情報が利用されます。面倒なセッション管理を実装する必要がないうえに、アカウント情報そのものをグーグルに依存することで、個人情報の管理コストを減らすこともできます。

 Users APIを利用するためには google.appengine.api からusersパッケージを読み込み、users.get_current_user()でUserオブジェクトを取得します。

from google.appengine.api import users
user = users.get_current_user()
if not user:
  # ユーザーはログインしていない
else:
  print "Hello, %s!" % user.nickname()

 Userオブジェクトには、ディスプレイ用のユーザー名を取得する nickname() メソッドとメールアドレスを取得する email() メソッドがあります。

 注意が必要なのは、ここで取得したメールアドレスの情報は後にサイトの外で変更される可能性があるということです。このため、GAEのデータベースに記録されたユーザー情報と現在のユーザーのマッチングを行うためには、UserProperty形式で直接Userオブジェクトを保存し、クエリに使用します(詳細は、Userオブジェクト解説ページのNotes:を参照してください)。

データオブジェクトの利用

 ユーザーから投稿されたデータを保存してアプリケーションで利用するには、データベースとの連携が不可欠です。GAEではDatastore APIを使用することでデータベースへのアクセスをオブジェクト経由で行うことができます。

 まずは、必要なデータベースの定義を行います。

from google.appengine.ext import db
class Log(db.Model):
  author = db.UserProperty()
  content = db.StringProperty(multiline=True)
  date = db.DateTimeProperty(auto_now_add=True)

 db.Modelを継承してデータオブジェクトクラスを定義します。UserProperty, StringProperty, DateTimePropertyは、それぞれユーザー情報、文字列情報、日付情報を格納するカラムの属性です。

 この定義が書かれたハンドラが実行されると、GAEは自動的にデータベースにテーブルとカラムを作成し、上記のオブジェクトからアクセス可能な状態にします。

 試しに、SDK環境のコンソール画面をチェックするとデータが定義されている様子が分かります。

SDK環境のコンソール画面
SDK環境のコンソール画面

 コンソール画面では、実際に格納されたデータを閲覧したり、新規作成、編集、削除などを行うことができます。

フォームからの入力を処理する

 データベースができたので、今度はユーザーからの入力を格納してみます。フォームからの入力を処理するコードは、下記のようになります。

import cgi
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext import db
class Log(db.Model):
  author = db.UserProperty()
  content = db.StringProperty(multiline=True)
  date = db.DateTimeProperty(auto_now_add=True)
class LogHandler(webapp.RequestHandler):
  def post(self):
    log = Log()
    log.content = self.request.get('content')
    log.put()
    self.redirect('/log/list')

 ハンドラpostを定義することで、フォームからのPOSTリクエストを処理できます。

 ここでは、self.request.get('content')で“content”パラメータを取得してLogオブジェクトのcontentカラムにセットし、log.put()メソッドでデータベースへの反映を行っています。

データの表示

 格納されたデータを表示するハンドラコードは下記のようになります。ここではURL“/log/list”のハンドラを定義してデータベースから取得したLogデータの内容を一覧表示しています。

 データを投稿するためのフォームも一緒に表示します。

class ListHandler(webapp.RequestHandler):
  def get(self):
    self.response.out.write('<html><body><ol>')
    logs = db.GqlQuery("SELECT * FROM Log ORDER BY date
 DESC LIMIT 10")
    for log in logs:
      self.response.out.write('<li>%s</li>' %
                              cgi.escape(log.content.encode('utf-8')))
    # Write the submission form and the footer of the page
    self.response.out.write("""
          </ol><form action="/log" method="post">
            <div><textarea name="content" rows="3" cols="60">
</textarea></div>
            <div><input type="submit" value="logme!"></div>
          </form>
        </body>
      </html>""")

 GqlQuery()を使用して、日付順にソートしたデータを10件表示しています。

 日本語のデータを扱う際に注意しないといけない点は、Pythonでは文字列はASCIIとして扱われているため表示を行う際にUTF-8などに変換をしてやる必要があることです。

 logからcontentデータを取り出した後encode(‘utf-8’)で変換を行っています。

SDK環境のコンソール画面
SDK環境のコンソール画面

 このハンドラの結果は下記のようになります。

GAEで自作Webアプリを多くのユーザーに使ってもらおう

 GAEを使ったWebアプリケーション開発の実際について駆け足で解説してきましたが、およその雰囲気をつかんでいただけたでしょうか?

 自分のマシンで動かしているWebアプリケーションが、面倒な運用の手間なしに公開されて多くのユーザーに使ってもらえる。GAEはそんなWebデベロッパーの夢を実現したサービスといえます。

 一方で、バッチ処理のような必須機能が未実装である点や、GAE環境の利用量が500万PV程度までに制限されていて超過した際のパスがないことなど、正式版でないが故の課題もまだ残っています(いずれも、2008年10月5日現在)。

 当面は、こうした課題が改善されるのを待ちながら、サービス開発をしてくことになるでしょう(500万PVの制限は、大抵の新規サービスにとってそれ自体が結構なハードルだとは思いますが)。

 GAEチームの頑張りに期待しましょう。

関連情報へのリンク

記事の都合上、まだまだ紹介し切れていない機能が多くあります。URL Fetch APIを使った外部情報の取得やDjangoなどのWebフレームワークの利用などに興味のある方は、下記のリンクなどを参考にしてください。

 なお、この記事で作成したアプリケーションは、「http://log-me.appspot.com/」でアクセスできます。徐々に機能を追加していく予定ですので、実例としてぜひご覧ください。

著者紹介

立薗理彦(たちぞの まさひこ)

1972年東京生まれ。1996年、慶應大学 環境情報学部卒。シャープで組み込み系のソフトウェアエンジニアとして働いた後、携帯電話メーカーのノキアで日本向け端末のリリースに携わる。

この頃、週末プロジェクトとしてiTunesでの再生履歴をネットで公開するサービス「音ログ」を開発。これをきっかけに、ウェブ業界への転身を決意してフリーに。

その後、音楽ニュースサイト「ナタリー」の立ち上げに関わり、2007年10月から技術担当取締役としてナターシャに参加。現在に至る。

最近の興味は、iPhoneでのアプリケーション開発。

趣味は、TVドラマ「Lost」を繰り返し見ること。全シーズンをすでに3回以上見ていて、ハワイでのロケ地ツアーにも2回参加。

著者つぶやき
http://mshk.tumblr.com/
http://twitter.com/mshk
http://friendfeed.com/rooms/sweet-tweet



Copyright © ITmedia, Inc. All Rights Reserved.

前のページへ |       
ページトップに戻る