以前調べた範囲では、Python3 + Djangoでは、MS Accessをバックエンドにするのは難しいものの、SQLAlchemy + pyodbc であれば、比較的楽にPython3からMS Accessへと接続できそうだとわかりました。
Python3を使ってMS Access(*.accdb)へ接続してみた - メモ的な思考的な
また、wfastcgiというライブラリを使うことで、WSGIアプリをIISでホストできることが分かったものの、Djangoだけしか試せていませんでした。
Django + IIS + wfastcgiで静的ファイル(CSS, JavaScriptなど)を配信する - メモ的な思考的な
そこで今回、それらを組み合わせた
を試してみました。
なお、MS AccessがなくてもFlaskをIISでホストできるため、記事のタイトルからは意図的にMS Accessを外してあります。
環境
- IIS 7.0
- 64bit OS
- データベース
- Accessファイル(accdb)
- Access Database Engine 2010 再頒布可能コンポーネント (32bit版)
- pyodbcで接続する時に必要
- Python 3.4.4 32bit版
- アプリ内で使うpyodbcの都合上、3.4系を使います*1。
- Flask 0.10.1
- SQLAlchemy 1.0.12
- sqlalchemy-access 0.8.dev0
- Bitbucketリポジトリからinstall
- pyodbc 3.0.10
- アプリ用のディレクトリ
D:\flask_iis
の下
Access Database Engineのインストール
今回はデータベースとしてAccessを使うので、以下よりAccess Database Engineをダウンロード・インストールします。
Download Microsoft Access データベース エンジン 2010 再頒布可能コンポーネント from Official Microsoft Download Center
今回のPython3.4は32bit版なので、Access Database Engineも32bit版(AccessDatabaseEngine.exe
)を使います。
Flaskアプリの動作環境を作成
今回は以下のアプリを使います。
thinkAmi-sandbox/Flask_ms_access_with_iis_sample
Flaskアプリの仕様を載せると長くなりそうなので、後述することにします。
コマンドプロンプトなどから、以下の作業を行います。
# GitHubにあるソースコードを、`d:\flask_iis`へと入れておく # virtualenv環境作成からライブラリのインストールまで d:\flask_iis>virtualenv -p c:\python34\python.exe env d:\flask_iis>env\Scripts\activate (env) d:\flask_iis>pip install -r requirements.txt (env) d:\flask_iis>pip list Flask (0.10.1) itsdangerous (0.24) Jinja2 (2.8) MarkupSafe (0.23) pip (8.1.1) pyodbc (3.0.10) setuptools (20.4) SQLAlchemy (1.0.12) sqlalchemy-access (0.8.dev0) Werkzeug (0.11.5) wfastcgi (2.2) wheel (0.29.0) # 動作確認(http://127.0.0.1:5000/) (env) d:\flask_iis>python server.py # 確認できたら、`Ctrl + C`で一度停止する
作成したディレクトリ構成は、以下の通りです。
d:\flask_iis ├── env\ (virtualenv環境) │ └── ... ├── static\ (CSS等のファイルを入れるディレクトリ) │ └── style.css ├── templates\ (FlaskアプリのJinja2テンプレートディレクトリ) │ └── index.html ├── requirements.txt ├── sample.accdb (MS Accessデータベース) ├── sample.xml (Flaskで表示するxmlファイル) ├── server.py (Flaskアプリ本体) └── web.config (wfastcgiによるIISホスト用の設定ファイル)
また、MS Access(sample.accdb
)のテーブル(Item)は、以下の通りです。
列名 | 型 |
---|---|
ID | オートナンバー |
item_name | テキスト |
設定値は以下の通りです。
ID | item_name |
---|---|
1 | ほげ |
2 | foo |
IISの設定
IISのインストール
IIS + CGIは、以下を参考にインストールします。
CGI
また、IIS7.0でwfastcgiを使う場合はKB980363が必要になりますので、IISのインストール後にパッチを適用します。詳細は過去記事に書きました。
IIS7.0 + Python3 + wfastcgi 構成のWSGIアプリ作成時に発生したエラーのメモ - メモ的な思考的な
Webサイトの追加
左ペインのサーバ名(http://localhost/)を右クリック、Webサイトの追加
を選択します。
以下の内容を入力します。
項目 | 値 |
---|---|
サイト名 | Flask wfastcgi |
コンテンツディレクトリ - 物理パス | D:\flask_iis |
バインド - ポート | 9753 (任意) |
なお、この時点でhttp://localhost:9753/
にアクセスすると、
HTTP エラー 403.14 - Forbidden Web サーバーは、このディレクトリの内容の一覧を表示しないように構成されています。
とブラウザに表示されます。
wfastcgiの設定
wfastcgiのPyPIページにある通り、wfastcgi-enable
を実行します。
wfastcgi 2.2 : Python Package Index
(env) d:\flask_iis>wfastcgi-enable 構成変更を構成コミット パス "MACHINE/WEBROOT/APPHOST" の "MACHINE/WEBROOT/APPHOST" のセクション "system.webServer/fastCgi" に適用しました "d:\flask_iis\env\scripts\python.exe|d:\flask_iis\env\lib\site-packages\wfastcgi.py" can now be used as a FastCGI script processor
web.configの作成
一番悩んだのがweb.configの設定ですが、今回は以下の通りとしました。
WSGI_HANDLER
wfastcgiのPyPIでは、設定内容について
This is a Python name that evaluates to the WSGI application object
と書かれていました。
設定内容の形式は、<Pythonファイル名>.<WSGIオブジェクト>
となるようです。
今回のFlaskアプリは
であったため、server.app
を指定しました。
- 参考
なお、同じくWSGIアプリケーションであるBottleもIISでホストできそうですが、
- IISに対応したBottleアプリの作り方
- その時の
WSGI_HANDLER
の設定内容
が分からない状況なので、今は試すことができていません。ご存じの方がいれば、教えていただけるとありがたいです。
PYTHONPATH
特に今回は値を指定しませんでしたが、環境に応じて設定します。
scriptProcessor
Djangoの時と同様、wfastcgi-enable
の結果をそのままコピペします。
ここを踏まえた、最終的な結果は以下のような内容となりました。これをD:\flask_iis\web.config
として作成します。
<configuration> <appSettings> <add key="WSGI_HANDLER" value="server.app" /> <add key="PYTHONPATH" value="" /> </appSettings> <system.webServer> <handlers> <add name="Python FastCGI" path="*" verb="*" modules="FastCgiModule" scriptProcessor="d:\flask_iis\env\scripts\python.exe|d:\flask_iis\env\lib\site-packages\wfastcgi.py" resourceType="Unspecified" requireAccess="Script" /> </handlers> </system.webServer> </configuration>
ファイアウォールの設定
セキュリティが強化されたWindowsファイアウォールから、使用するTCPポート9753
を開けます。
項目 | 値 |
---|---|
規則の種類 | ポート |
プロトコルおよびポート - 規則 | TCP |
プロトコルおよびポート - 特定のローカルポート | 9753 |
操作 | 接続を許可する |
プロファイル | 今回は、すべてにチェックを入れる |
名前 | Inbound for Flask app |
動作確認
http://<ipアドレス>:9753
にアクセスし、動作を確認しました。
Flaskアプリの仕様
Flask公式ページにあるHello Worldアプリでも良かったのですが、Flaskアプリの作り方を知る良い機会だったので、以下の仕様としました。
GET /
でJinja2テンプレートのフォームを表示POST /
で、フォームで入力した値を元に、Accessからデータを取得し、テンプレート中の変数に反映GET /xml
で、用意したxmlファイルをそのまま表示
作る時に悩んだ内容は、以下にまとめておきます。
Flaskまわり
@app.route('/', methods=['GET', 'POST'])
のようなデコレータを使うことで、GET以外のHTTPメソッドも受け付けるif request.method == 'POST':
のようにPOSTかどうかを判定
- フォームでPOSTされた値は、
request.form[<フォームのname属性>]
で取得 - xmlファイルをそのまま返す場合、
send_file(<xmlファイル名>)
を使う - スニペットは次にある:Snippets Archive | Flask (A Python Microframework)
Jinja2テンプレートまわり
FlaskでHTMLを表示するためのテンプレートとして、Jinja2を使いました。
- テンプレートは、
templates
ディレクトリの下に置く- 今回は、
D:\flask_iis\templates\index.html
- 今回は、
- テンプレート内でCSSを参照するには、
<link ... href="{{ url_for(<ファイルがあるディレクトリ名>, filename=<CSSファイル名>) }}"/>
のように書く - テンプレートで変数を扱う(ここでは、変数
message
)- Flaskで
render_template("index.html", message=None)
のようにテンプレートへ渡す - テンプレートで
{{ message }}
のように参照する
- Flaskで
- テンプレートで
None
かどうかを判定する{% if message is not none %}
のように、Jinja2のnoneを使う- 参考: flask - Jinja2 template variable if None Object set a default value - Stack Overflow
SQLAlchemyまわり
- connectionやengineを使ったら、
connection.close()
とengine.dispose()
を忘れずに行う- engine.dispose()を忘れると、Accessのロックファイル
laccdb
が残ったままになる - 参考
- engine.dispose()を忘れると、Accessのロックファイル
requirements.txtまわり
- Bitbucketなどで公開されているzipをpipでinstallしたい場合は、そのまま書く
https://bitbucket.org/zzzeek/sqlalchemy-access/get/default.zip
ソースコード
再掲となりますが、GitHubに上げてあります。
thinkAmi-sandbox/Flask_ms_access_with_iis_sample