いろいろやってきた環境構築を繋げます。
前提とか
アプリ側(Flask)の環境構築は以下とか。
DB側(MongoDB)の環境構築は以下とか。
上記と同等レベルの環境構築が完了していることを前提としています。
今回レベルの実装なら多分プログラムの実装より環境構築の方が大変かもしれないです。
全て同一サーバ(VirtualBox)上に構築しています。
全体像
構築イメージ
なんとなくのイメージ図です。
ブラウザなどからアクセスがあるとFlaskアプリである「main.py」にアクセスがあり(①)、そこから今回のメイン部分であるMongoDBへのアクセス(②、③)があります。
取得したデータをそのまま返すだけでは味気なかったので、HTMLファイルにDBから取得したデータを埋め込んで(④、⑤)、HTMLをブラウザに返却します。
ディレクトリ構成
/usr/share/nginx/app/sample
├main.py
└templates
└index.html
ルートはどこでもよいです。
今回の場合はNginxの環境構築のものを引き継いでいるので「/usr/share/nginx/app/sample」をルートしてそこに「main.py」を配置します。
pythonソースの名前は任意ですが、HTMLファイルを格納するディレクトリ名は原則固定なようです。
pythonソースと同じ階層に「/templates/」というディレクトリを作成しそこにHTMLファイルを格納します。
ソース
このあと細かく見ていきますが先にサンプルソースを掲載しておきます。
Flask(Python)のソースとhtmlファイルです。
・main.py
from flask import Flask, render_template from pymongo import MongoClient application = Flask(__name__) #デフォルトルート @application.route('/') def index(): client = mongo_init() sample = client.test.doc.find() return render_template('index.html',contents=sample) def mongo_init(): host = 'localhost' port = 27017 db = 'test' user = 'wantan' pwd = 'wantan' client = MongoClient(host, port) client[db].authenticate(user, pwd) return client
・index.html
{% block page_content %} <h1>Sample List</h1> <div> <table> <thread> <tr> <th>name</th> <th>num</th> <th>type</th> </tr> </thread> <tbody> {% for sample in contents %} <tr> <td>{{ sample.name }}</td> <td>{{ sample.num }}</td> <td>{{ sample.type }}</td> </tr> {% else %} <td>no entry exist!</td> {% endfor %} </tbody> </table> </div> </div> {% endblock %}
MongoDBに接続する
アクセス準備
DBへのアクセス
・main.pyの抜粋
# 1)MongoClientをインポートする from pymongo import MongoClient # Mongoクライアントオブジェクトの初期化関数 def mongo_init(): #2)変数の設定 host = 'localhost' port = 27017 db = 'test' user = 'wantan' pwd = 'wantan' # 3)クライアントオブジェクトの生成 client = MongoClient(host, port) # 4)DBのユーザ認証 client[db].authenticate(user, pwd) # クライアントを返却する return client
1)MongoClientをインポートする
pythonでMongoDBを使用するには「MongoClient」と言われるクラスをpymongoからインポートします。
インストールされていない場合には先にサーバでpipからインストールするようにしましょう。
2) 変数の設定
クライアントオブジェクトを生成するための変数を設定しています。もちろん直接指定しても問題はありません。
3)クライアントオブジェクトの生成
インポートしたMongoClientで接続先を指定してオブジェクトを生成します。
4)DBのユーザ認証
ユーザ認証を設定している場合には、ユーザ認証を行います。
認証を設定しない場合にはそのままでも使用できるはずです。
注意点としては「client[db]」でDBを指定する必要がある点ぐらいでしょうか。
最後に生成したクライアントオブジェクトを呼び出し元に返却します。
DBからドキュメントを取得
クライアントの生成が正しくできていればあとは取得するだけです。
#デフォルトルート @application.route('/') def index(): # 1)クライアントオブジェクトを初期化する client = mongo_init() # 2)ドキュメントの全取得 sample = client.test.doc.find() # 3)テンプレートに取得値を埋め込み返却 return render_template('index.html',contents=sample)
1)クライアントオブジェクトを初期化する
前述のとおり、オブジェクトを生成し接続先指定、認証を行う。
2)ドキュメントの全取得
対象のコレクションからドキュメントを全取得します。
client.[DB].[コレクション].[命令]の形式で指定をします。
テーブルの結合は原則できませんが、挿入更新削除、条件を絞った検索など一般的なRDBと同様の命令が実行できます。今回はもっとも簡単で分かりやすい全取得のみ。
3)テンプレートに取得値を埋め込み返却
後述します。
HTMLファイルを返却する
HTMLファイルを読み込む
flaskを使用すると簡単にHTMLファイルも読み込めるようなのでおまけでつけました。
・main.pyの抜粋
# 1) render_templateをインポート from flask import Flask, render_template def index(): # 2) HTMLファイルの読み込み return render_template('index.html',contents=sample)
1) render_templateをインポート
HTMLファイルの読み込みのため、flaskからrender_templateをインポートします。
flaskがインストールできていればそのままインストールできるはずです。
2) HTMLファイルの読み込み
render_templateの第一引数が読み込みを行うHTMLファイル(テンプレート)になり、前述のディレクトリ構成を作りファイルを配置すればそれだけで読み込めるようになるみたいです。
第二引数には埋め込みを行うパラメータを指定します。
MongoDBの場合は取得値をそのまま渡せば、それだけで正しくパラメータリストとして認識されるようです。
HTMLファイル側の実装については後述します。
HTMLファイルにパラメータを埋め込む
・index.htmlの抜粋
<!-- 1)パラメータリストをfor文で列挙する --> {% for sample in contents %} <tr> <!-- 2)オブジェクトから要素を取り出して出力する --> <td>{{ sample.name }}</td> <td>{{ sample.num }}</td> <td>{{ sample.type }}</td> </tr> <!-- 一件も存在しない場合のデフォルト出力--> {% else %} <td>no entry exist!</td> <!-- for文の終わり--> {% endfor %}
1)パラメータリストをfor文で列挙する
contentsというパラメータリストをfor文によりsampleと名付けたオブジェクトごとに出力していきます。
2)オブジェクトから要素を取り出して出力する
sampleオブジェクトから要素を取り出していき出力します。
オブジェクト名はその場で勝手に命名しましたが、要素名はMongoDB内のドキュメントの列に対応しています。
画面の表示結果
最後にブラウザからアクセスした際の画面表示結果は以下のようになります。
リストで表示するようにしたとはいえ、CSSがないと何とも味気ない感じになりますね。
ーーーーーーーーーーーーーー
とりあえずここまででひと段落になります。次回以降は本流に戻る予定。