【snake】Section: 11 Creating a Contact Form

requirements.txtに追加する。

Celeryを使えばタスクを別のスレッドやマシンに分散することができる。このタスクを分散させる仕組みをタスクキューといい、Celeryのプロセスは新しいタスクが入ってきていないかタスクキューを監視する。よくわからんけど、redisがメッセージの運び屋で、celeryが振り分け処理をするらしい。

# Data and workers.
redis==2.10.5
celery==3.1.23

# Forms.
Flask-WTF==0.9.5
WTForms-Components==0.9.7

# Extensions.
flask-debugtoolbar==0.10.0
Flask-Mail==0.9.1

WTForms-Componentsは別の作者が作ったもので、
wtfより更にいろんなformを使えるようになる。

e-mailの設定方法

config/setting.pyでサーバーなどの設定を行う。 f:id:yukking3:20180708193906p:plain

instance/setting.py ここに登録しておく。 f:id:yukking3:20180708194234p:plain

lib/flask_mailplus.py f:id:yukking3:20180813155749p:plain これを設定することでパラメーターが使えるようになる。 f:id:yukking3:20180813155825p:plain

Contact Blueprint

blueprints/contacts/forms.pyを新しくblueprintを追加している。 f:id:yukking3:20180710092834p:plain

追加したblueprintをapp.pyでインポートする。 f:id:yukking3:20180710093006p:plain

そして、55行目でregisterされている。 f:id:yukking3:20180710093133p:plain

Extentionに色々追加されている。 mailエクステンションやFlask wtf packgeからcsrfが登録されている。 f:id:yukking3:20180710212610p:plain



Views.pyに関して

f:id:yukking3:20180813194402p:plain 場所は、snakeeyes/blueprints/contact/views.pyである。
形は他のblueprintと同じである。
①インポートして
②blueprint作って
③roteを作る。


f:id:yukking3:20180708222432p:plain ここからは各行ごとの役割を解説する。

14行目は、methods=['GET', 'POST'] はhtmlの出し入れを行う
25行目は、submitされた際にメッセージを表示させる。
26行目は、送信後に contact.index にリダイレクトさせる。
28行目は、indexに送る。form=formは、flaskがjinja2へvariableを送る方法。

今回はwtu formが使われている。16行目でform定義されている。
つまり、18行目のif文でエラーがなければflashメッセージが表示されリダイレクトする。



TemplatesとMacrosに関して

fは for macro のfである。
【Macrosの説明は意味がわからないので飛ばす。】

f:id:yukking3:20180813192541p:plain blueprints/contact/templates/contact/index.html を使う。 f:id:yukking3:20180813193022p:plain call f.form_groupを使う。 f:id:yukking3:20180813193311p:plain macroを使って、エラーチェックをする。

次にform tagである。 f:id:yukking3:20180813193059p:plain ここではcall f.form_tagを使う。 f:id:yukking3:20180813193834p:plain 全てのタグを送込んでくれるmacroらしいが、現時点ではいまいちよく分からない。



Flask-WTForms

f:id:yukking3:20180813200149p:plain

EmailFieldはwtfではないのでwtforms_componentsからインポートしている。
ContactFormを作る。wtfからFormを受け継いでくる。
入力文字数は制限した方がいい。→ Length(3, 254)]こんな感じ。
f:id:yukking3:20180710220604p:plain

views.pyを見て見る。
9行目でContactFormをインポートする。
16行目でインスタント化している。
18行目でif文で確認を行なっている。
f:id:yukking3:20180710220930p:plain


/contact/index.html を確認して見るとemaiフィールドとmessageフィールドがある。
emailとmessageは、適切に入力されているか確認するform.pyとマッチングするようになっている。 f:id:yukking3:20180710221201p:plain


Celeryでメールを送る。

16〜17行目は、/0はredisのデータベースの名前である。
18〜20行目は、jsonのみ受け入れできるようにしている。セキュリティ状の問題である。
21行目は、コネクション制限である。
f:id:yukking3:20180710222114p:plain

メールの設定方法
メールアドレスとパスワードを設定する。
その際にgoogleでアプリパスワードの設定が必要。 f:id:yukking3:20180713090103p:plain 続けてパスワードの設定をする。 f:id:yukking3:20180713090132p:plain

実際に試してみる f:id:yukking3:20180713090426p:plain メールをgmail.comで確認できる。 f:id:yukking3:20180713090501p:plain

Celery with Docker Compose

docker-compose.ymlが何を書いてるか読み解く。
病むファイルは、コンテナに自動で環境設定してくれる環境設定まとめファイル。
6行目は、パスワードを設定する。configファイルとマッチさせなければならない。マストではない。
8行目は、volume。これを設定することでコンテーナーを止めてから変更したものなどを保存できる。次にコンテナを起動させて場合もそのデータは失われない。
34行目と36行目は同じ名前になる。
10行目は、ポート番号を入力する。これはredisのデフォルト設定。

f:id:yukking3:20180713091427p:plain

更なる詳細は以下の通りである。

version: '3'                                    # docker-composeの使用バージョン
services:                                       # コンテナから作られるサービス達。コンテナの設定を以下に。
  nginx:                                         # コンテナの名前
    build:                                        # イメージ(コンテナのテンプレ)を作るためのDockerfileがある場所
      context: ./nginx                    # Dockerfileの場所
    depends_on:                           # 対象のコンテナとリンク。 /etc/hostsにローカルipが書かれる
      - php                                     # 172.17.0.3 php とか書かれる
    ports:                                      # 公開port
      - 80:80                                  # 外部公開ポート番号 : コンテナのポート番号
    volumes:                                  # マウント。コンテナのデータと、手元のデータが同期する。
      - ./www:/var/www:cached     # 手元のパス : コンテナのパス : キャッシュオプション

  php:
    ~略~

  mysql:
    restart: always                     # コンテナが止まった時に再起動する
    image: mysql:latest             # コンテナを作るためのイメージ
    volumes:
      - ./mysql:/var/lib/mysql
    environment:                         # 環境変数の設定
      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
      - MYSQL_DATABASE=${MYSQL_DATABASE}
    ports:
      - 3306:3306



Confirming Tests:コンタクトページが動いているかテストする

asert分とは、成立している確認する関数。予期しない値を持った際には AssertionError を発生させ、エラーメッセージとともにプログラムを停止します。

assert 条件式, メッセージ

#メッセージは省略することができます。


f:id:yukking3:20180813202112p:plain 今回見るテストコードは前回と違いpost requestを実行するテスト。
14行目でtest_contact function内にformを辞書型で作りその中にemailとmessage書く。
19行目でpost clientを使ってdata(form)を送り込んでredirectさせる。
21行目でassert文を使ってresponseがthanksメッセージ付きの200か確認する。
f:id:yukking3:20180714151654p:plain
assert_status_with_messageファンクションを確認する。
メッセージ付きのcustom assertionsを作る。
f:id:yukking3:20180813202733p:plain

カスタムアサーションが何をするこというとメッセージ付きのresponseが帰って来るか確認する。13行目でstatus_codeを確認する。14行目で特定のhtm形式のメッセージを受け取れるかを確認する。 f:id:yukking3:20180714152009p:plain


test_task.pyに関して
f:id:yukking3:20180813204023p:plain Cellery taskがどう動くかとflaskのメールextentionのoutboxがど動くかを理解できる。
8行目で辞書型でformを作る。
13行目でoutboxにメールを送る。
16行目でassert文を使って1通のみ送られたかをテストする。
17行目でoutboxの1文目がemailであるかをテストする。
f:id:yukking3:20180714152745p:plain

実際にコードがtestを試して見る。

$ docker-compose exec website snakeeyes test

実行すると6つのテストのpassを確認できる。 f:id:yukking3:20180714143926p:plain

コンタクトページの何割をtestコードでカバーしているか確認する。

$ docker-compose exec website snakeeyes cov

実行すると100%クリアであると確認できる。 f:id:yukking3:20180714144042p:plain