チュートリアル gae-init

# チュートリアル

> このチュートリアルは、[gae-initのTurorial](http://docs.gae-init.appspot.com/tutorial/)を元に翻訳し、動作検証しています。


このチュートリアルでは、出発点としてgae-initを使用して簡単な電話帳アプリケーションを開発する方法について説明します。パーソナル電話帳を作成することで、アプリケーションを開発、作成、実行、およびデプロイする方法を学習します。

# 1. はじめに
始める前に、次の開発環境に関する要件を確認してください。
[Python 2.7](http://docs.gae-init.appspot.com/requirement/#python)、[Google Cloud SDK](http://docs.gae-init.appspot.com/requirement/#gcloud)、[Google App Engine](http://docs.gae-init.appspot.com/requirement/#gae)、[Node.js](http://docs.gae-init.appspot.com/requirement/#nodejs)、[Gulp](http://docs.gae-init.appspot.com/requirement/#gulp)、[pip](http://docs.gae-init.appspot.com/requirement/#pip)、[virtualenv](http://docs.gae-init.appspot.com/requirement/#virtualenv)、[Git](http://docs.gae-init.appspot.com/requirement/#git)

このチュートリアルは、Google App Engineがどのように機能するのかを説明したり、Pythonでコーディングする方法を説明したりするトピックではありません。したがって、これらのトピックに慣れていない場合は、このトピックを続ける前に少なくとも[入門ガイド：Python 2.7](https://developers.google.com/appengine/docs/python/gettingstartedpython27/)を確認しておくと良いでしょう。

## Windows Subsystem for Linux (Ubuntu) での準備
Windows 10 で、ストアから Ubuntu をインストールし、次の手順で開発環境を準備してください。

``` bash
sudo apt -y update
sudo apt -y upgrade
sudo apt -y autoremove

sudo apt -y install python

curl https://sdk.cloud.google.com | bash
gcloud components install app-engine-python

sudo apt -y install nodejs
sudo apt -y install npm
sudo apt -y install yarn

sudo npm install -g gulp

curl https://bootstrap.pypa.io/get-pip.py | sudo python
sudo pip install virtualenv

sudo apt -y install git
```

# 2. コードを入手する
Gitを使用してgae-initプロジェクトのクローンを作成し、コードをコンピューターのローカルに取得します。

```
$ git clone https://github.com/gae-init/gae-init.git phonebook
```

これで、phonebookというディレクトリが作成されます。ここには、mainなどの他のディレクトリも含まれており、ここにすべてのソースファイルやライブラリなどが存在します。

# 3. アプリケーションを実行します
Google App Engine アプリケーションをコマンドラインから実行する方法を既に知っていることを前提としています。そうでない場合は[ドキュメント](https://developers.google.com/appengine/docs/python/gettingstartedpython27/helloworld)を参照してください。
次のようにターミナルウィンドウで、ルートディレクトリから gulp を実行してください。

```
cd phonebook
npm install
gulp
```


すべてうまくいった場合は、Webブラウザで次のURLにアクセスしてアプリケーションをテストできます（自動でブラウザーが起動します）。

```
http://localhost:3000/
```

まず、最初の設定変更として、アプリへ管理者としてサインインし、 http://localhost:3000/admin/config/ にアクセスします。ブランド名(Brand Name)を「None」から「電話帳」（または他の好きなもの）に変更します。そうすると、アプリケーションの新しい名称が左上隅に表示されるはずです。

# 4. 新しいモデルを追加します
パーソナル電話帳を作成するためには、連絡先リストをデータストアに保存する必要があります。

main/model ディレクトリ内に 次の内容で、 contact.py というファイルを作成します。

``` python
from google.appengine.ext import ndb
import model

class Contact(model.Base):
  user_key = ndb.KeyProperty(kind=model.User, required=True)
  name = ndb.StringProperty(required=True)
  email = ndb.StringProperty(default='')
  phone = ndb.StringProperty(default='')
  address = ndb.StringProperty(default='')
```

このuser_keyプロパティには、連絡先リストをすべてのユーザーが個人用にするためのユーザーキーが格納されます。残りのプロパティはその名の通りです。

最後にこれを main/model/\_\_init\_\_.py ファイルで次のようにインポートします。

``` python
from .contact import Contact
```

# 5. 連絡先を追加する
データストアに新しい連絡先を追加するために必要なことがいくつかありますが、簡単に言えば、フォーム、ハンドラー、そして、テンプレートを作成すればよいのです。

## 1) 連絡先の生成フォーム
main/controlディレクトリにcontact.pyファイルを新たに作成し、ユーザー入力を検証する役割を果たす次のコードを追加します。

``` python
import flask_wtf
import wtforms

class ContactUpdateForm(flask_wtf.FlaskForm):
  name = wtforms.StringField('Name', [wtforms.validators.required()])
  email = wtforms.StringField('Email', [wtforms.validators.optional(), wtforms.validators.email()])
  phone = wtforms.StringField('Phone', [wtforms.validators.optional()])
  address = wtforms.TextAreaField('Address', [wtforms.validators.optional()])
```

フォーム検証に関する詳細は[Flask-WTForms(英語)](http://flask.pocoo.org/docs/patterns/wtforms/)を参照してください。

## 2) 連絡先の生成ハンドラー
フォームを作成したら、それに対するハンドラーを作成する必要があります。main/control/contact.pyファイルに次のコードを追加します。

``` python
import flask
import auth
import model

from main import app
```

``` python
@app.route('/contact/create/', methods=['GET', 'POST'])
@auth.login_required
def contact_create():
  form = ContactUpdateForm()
  if form.validate_on_submit():
    contact_db = model.Contact(
        user_key=auth.current_user_key(),
        name=form.name.data,
        email=form.email.data,
        phone=form.phone.data,
        address=form.address.data,
      )
    contact_db.put()
    return flask.redirect(flask.url_for('welcome'))
  return flask.render_template(
      'contact_create.html',
      html_class='contact-create',
      title='Create Contact',
      form=form,
    )
```

この追加した新しいスニペットを詳しく見ていきましょう。

``` python
import flask
import auth
import model

from main import app
```

ここには、ハンドラーとして必要な import が含まれています。そのほかの import と同様に main/contact.py ファイルの先頭に配置するだけです。

``` python
@app.route('/contact/create/', methods=['GET', 'POST'])
```

使用するルートとメソッドを定義します。GETは、HTMLフォームを提供し、POSTは、データを送り返します。
詳細については、[ルーティング(英語)](http://flask.pocoo.org/docs/quickstart/#routing)に関するFlaskのドキュメントを参照してください。

``` python
@auth.login_required
```

このデコレータの目的は、このURLを入力している人がすでにサインインされていることを確認して、認証されたユーザーの user_key を使用できるようにすることです。ユーザーがログインしていない場合は、サインインページにリダイレクトされてからこのURLに戻ります。

main/control/\_\_init\_\_.py ファイルで、contact を import しておきます。

``` python
from .contact import *
```

## 3) 連絡先の生成テンプレート
フォームとハンドラーを作成した後は、フォームに入力し、ユーザーデータを取得するためのテンプレートが必要になります。基本的に、これは先に作成したフォームへのユーザーインターフェースと考えることができます。templatesディレクトリに新しいファイルcontact_create.htmlを作成し、そこに次のコードを貼り付けます。

``` html
# extends 'base.html'
# import 'macro/forms.html' as forms

# block content
  <div class="page-header">
    <h1>{{title}}</h1>
  </div>
  <div class="row">
    <div class="col-md-4">
      <form method="POST" action=".">
        <fieldset>
          {{form.csrf_token}}

          {{forms.text_field(form.name, autofocus=True)}}
          {{forms.email_field(form.email)}}
          {{forms.text_field(form.phone)}}
          {{forms.textarea_field(form.address)}}

          <button type="submit" class="btn btn-primary btn-block">
            Create Contact
          </button>
        </fieldset>
      </form>
    </div>
  </div>
# endblock
```

## 4) トップバーにリンクを追加する
ユーザーが電話帳の周りを見回して連絡先を追加できるようにするには、トップナビゲーションバーへのリンクを作成する必要があります。

templates/bitディレクトリにあるheader.htmlファイルにある \<ul class="nav">...\</ul>要素内の2行目から４行目までを追加します。

``` html
<ul class="nav navbar-nav">
  <li class="{{'active' if html_class == 'contact-create'}}">
    <a href="{{url_for('contact_create')}}"><i class="fa fa-file"></i> Create Contact</a>
  </li>
  ...
</ul>
```

## 5) 連絡先生成のテストをする
開発サーバーがまだ実行中の場合は、http://localhost:3000/ にアクセスすると、上部のナビゲーションバーに\[Create Contact\]リンクが表示され、実際に新しい連絡先の生成を開始することができると思います。

\[Create Contact\]ボタンをクリックし、新しい連絡先をいくつか生成します。名前のない連絡先を追加してみたり、無効な電子メールを入力してみたりしてください。

連絡先リストはまだアプリケーションで表示できていませんが、管理コンソールにアクセスして、連絡先が追加されていることを確認できます。
Google App Engineの管理コンソールへのアクセス: http://localhost:8081/datastore

# 6. 連絡先を一覧表示する
連絡先を表示するには、3つのことを行う必要があります。データストアから連絡先を取得するハンドラーの作成、ブラウザに表示するテンプレートの作成、およびこのリストにアクセスするためのトップバーのリンクの作成です。

## 1) 連絡先リストハンドラー
contact.pyファイルに次のコードを追加します。

``` python
import util
```

``` python
@app.route('/contact/')
@auth.login_required
def contact_list():
  contact_dbs, contact_cursor = model.Contact.get_dbs(
      user_key=auth.current_user_key(),
    )

  return flask.render_template(
      'contact_list.html',
      html_class='contact-list',
      title='Contact List',
      contact_dbs=contact_dbs,
      next_url=util.generate_next_url(contact_cursor),
    )
```

## 2) 連絡先リストテンプレート
ハンドラーを作成したら、これまでに追加したすべての連絡先のテーブルを表示できるようにするためのテンプレートが必要になります。templatesディレクトリに新しいファイルcontact_list.htmlを作成し、そこに次のコードを貼り付けます。

``` html
# extends 'base.html'

# block content
  <div class="page-header">
    <h1>{{title}}</h1>
  </div>
  <table class="table table-bordered">
    <thead>
      <tr>
        <th>ID</th>
        <th>Name</th>
        <th>Email</th>
        <th>Phone</th>
        <th>Address</th>
      </tr>
    </thead>
    <tbody>
      # for contact_db in contact_dbs
        <tr>
          <td>{{contact_db.key.id()}}</td>
          <td>{{contact_db.name}}</td>
          <td>{{contact_db.email}}</td>
          <td>{{contact_db.phone}}</td>
          <td>{{contact_db.address}}</td>
        </tr>
      # endfor
    </tbody>
  </table>
# endblock
```

URL\: http://localhost:3000/contact/ に直接アクセスしてハンドラーとこのテンプレートをテストできますが、次のセクションではアクセスを容易にするためにリンクを追加します。

## 3) 連絡先リストの完成
最後の仕上げとして、トップバーにリンクを追加することと、連絡先を作成した後にウェルカムページに戻るのではなく、リダイレクトを変更してこのリストに移動することの2つを行います。

###トップバーにリンクを追加する
templates/bitディレクトリにあるheader.htmlファイルにある\<ul class="nav navbar-nav">...\</ul>要素内に3行目から5行目までを追加します。

``` html
<ul class="nav navbar-nav">
  ...
  <li class="{{'active' if html_class == 'contact-list'}}">
    <a href="{{url_for('contact_list')}}"><i class="fa fa-list"></i> Contact List</a>
  </li>
  ...
</ul>
```

ページを更新した後（ http://localhost:3000/ ）、上部にリンクが表示されるはずです。また、連連絡先リストを見ている場合は、それもアクティブになっているはずです。

###リダイレクトを変更する
新しい連絡先を生成したら、Welcomeページではなく連絡先リストにユーザーをリダイレクトします。また、新しい連絡先が正常に生成されたことを示すメッセージも表示します。

contact_createハンドラーで次の行を見つけます。

``` python
return flask.redirect(flask.url_for('welcome'))
```

そしてそれを次のように置き換えます。

``` python
flask.flash('New contact was successfully created!', category='success')
return flask.redirect(flask.url_for('contact_list', order='-created'))
```

最初の行は、作成が成功したというメッセージを点滅させることです。引数はcategoryオプションで、warning（デフォルト）、 danger、successまたはinfoのいずれかです。

2行目のurl_for関数で、order='-created'を使用していることに注目してください。これは、http://localhost:3000/contact/?order=-created に変換されます。好みに応じてどんな順序でも選ぶことができ、Contactモデルにあるフィールドであれば、様々な順序を指定するURLにすることができます。降順が必要な場合は、「-」記号を使用し、複数のフィールドを組み合わせる場合は「,」で区切ります。

# 7. 連絡先の表示
連絡先を表示するには、次の3つの作業を行う必要があります。データストアから連絡先を取得するハンドラーの作成、ブラウザで表示するためのテンプレートの作成、そして、連絡先リストのリンクから簡単にアクセスできるようにします。

## 1) 連作先ビューハンドラー
contact.pyファイルに次のコードを追加します。

``` python
@app.route('/contact/<int:contact_id>/')
@auth.login_required
def contact_view(contact_id):
  contact_db = model.Contact.get_by_id(contact_id)
  if not contact_db or contact_db.user_key != auth.current_user_key():
    flask.abort(404)
  return flask.render_template(
      'contact_view.html',
      html_class='contact-view',
      title=contact_db.name,
      contact_db=contact_db,
    )
```

## 2) 連絡先ビューテンプレート
ハンドラーを作成したら、連絡先の個人用ページを表示できるようにするためのテンプレートが必要になります。templatesディレクトリに新しいファイルcontact_view.htmlを作成し、そこに次のコードを貼り付けます。

``` html
# extends 'base.html'

# block content
  <div class="page-header">
    <h1>{{title}}</h1>
  </div>
  <p>{{contact_db.email}}</p>
  <p>{{contact_db.phone}}</p>
  <p>{{contact_db.address}}</p>
  <hr>
  <p>
    <a href="{{url_for('contact_list')}}">Back</a>
  </p>
# endblock
```

URLを手動で作成する必要があるため、今すぐこのフォームをテストするのは困難ですが、次のセクションでは、アクセスしやすくするためにリンクを追加します。

## 3) 連絡先ビューの仕上げ
連絡先を表示するための最後の仕上げとして、連絡先リストを変更します。連絡先の名前をクリックすると、連絡先を表示できるようになります。

連絡先の名前を表示している行を見つけて、次の行に置き換えます。

``` html
...
<td>
  <a href="{{url_for('contact_view', contact_id=contact_db.key.id())}}">
    {{contact_db.name}}
  </a>
</td>
...
```

ここで、連絡先リスト（ http://localhost:3000/contact/ ）にアクセスしてみると、それぞれの連絡先の名前をクリックできます。そうすると、それぞれの連絡先のプロパティを見ることができるはずです。

# 8. 連絡先を更新する
連絡先を更新するには、次の3つのことを行う必要があります。データストアから連絡先を取得するハンドラーの作成、ブラウザで連絡先を更新するためのテンプレートの作成、および簡単にアクセスできる連絡先リストのリンク作成です。

このステップでは、連絡先の生成と表示で見てきたように、もとてもよく似たアクションがあります。最後のステップでは、作成テンプレートと更新テンプレートを組み合わせて、テンプレートを1つだけ維持します。

## 1) 更新ハンドラへの連絡
contact.pyファイルに次のコードを追加します。

``` python
@app.route('/contact/<int:contact_id>/update/', methods=['GET', 'POST'])
@auth.login_required
def contact_update(contact_id):
  contact_db = model.Contact.get_by_id(contact_id)
  if not contact_db or contact_db.user_key != auth.current_user_key():
    flask.abort(404)
  form = ContactUpdateForm(obj=contact_db)
  if form.validate_on_submit():
    form.populate_obj(contact_db)
    contact_db.put()
    return flask.redirect(flask.url_for('contact_list', order='-modified'))
  return flask.render_template(
      'contact_update.html',
      html_class='contact-update',
      title=contact_db.name,
      form=form,
      contact_db=contact_db,
    )
```

## 2) 連絡先更新テンプレート
ハンドラーの後、ユーザーの詳細を更新できるようにするためにテンプレートが必要になります。templatesディレクトリに新しいファイルcontact_update.htmlを作成し、そこに次のコードを貼り付けます。

``` html
# extends 'base.html'
# import 'macro/forms.html' as forms

# block content
  <div class="page-header">
    <h1>{{title}}</h1>
  </div>
  <div class="row">
    <div class="col-md-4">
      <form method="POST" action=".">
        <fieldset>
          {{form.csrf_token}}
          {{forms.text_field(form.name, autofocus=True)}}
          {{forms.email_field(form.email)}}
          {{forms.text_field(form.phone)}}
          {{forms.textarea_field(form.address)}}
          <button type="submit" class="btn btn-primary btn-block">
            Update Contact
          </button>
        </fieldset>
      </form>
    </div>
  </div>
# endblock
```

## 3) 連絡先更新の仕上げ
最後の仕上げとして、連絡先リストへのリンクを追加して連絡先の更新ページに簡単にアクセスできるcontact_create.htmlようにしcontact_update.htmlます。また、と非常によく似ているので、削除します。

### 連絡先リストにリンクを追加する
連絡先のIDを表す行を見つけて、それを次の行に置き換えます。

``` html
...
<td>
  <a href="{{url_for('contact_update', contact_id=contact_db.key.id())}}">
    {{contact_db.key.id()}}
  </a>
</td>
...
```

これで、連絡先リスト（ http://localhost:3000/contact/ ）にアクセスしてください。それぞれの連絡先のIDをクリックして、その連絡先のプロパティを更新することができるはずです。

### contact_create.htmlを取り除く
今のところ、contact_create.htmlファイルとcontact_update.htmlファイルとの唯一の違いは、Submitフォームのキャプションです。contact_create.htmlフォームを削除して、contact_update.htmlにあるbutton要素を次のように変更してください。

``` html
...
<button type="submit" class="btn btn-primary btn-block">
  # if contact_db
    Update Contact
  # else
    Create Contact
  # endif
</button>
...
```

最後に、contact_create.htmlを削除したので、正しくテンプレートをレンダリングするために生成ハンドラーを単に更新する必要があります。今なら、読者のみなさんは自分自身でそれを見つけることができるはずです。

# 9. デプロイ
App Engine上で新しいアプリケーションを作成したこととapp.yamlで application の名前がで更新されていることを確認します。

アプリケーションをデプロイするには、ルートディレクトリ(phonebook)から次のコマンドを実行します。

``` bash
gulp deploy
```

オンラインで新しい連絡先を追加してアプリケーションをテストしましょう。

>ソースコードとデモ
>このチュートリアルのコードを[GitHub](https://github.com/gae-init/phonebook)から入手する か、実際の結果（[Phonebook](http://phonebook.gae-init.appspot.com/)）を確認して下さい。

# 10. 日本語表示の文字化け
もしかすると、日本語表示が文字化けするかもしれません。
main/templates/base.html ファイルの2行目のlang属性の値を"en"から"ja"に修正してください。

``` html
<html class="{% block html_class %}{{html_class}}{% endblock %}" lang="en">
```

``` html
<html class="{% block html_class %}{{html_class}}{% endblock %}" lang="ja">
```

>次のステップ
[How To セクション(英語)](http://docs.gae-init.appspot.com/howto/)へ進んでください。プロのようにgae-initで一般的なタスクを達成するためにどのようにしたらよいかを学ぶことができます。