Python + FlaskでMVC的なことをやってみた
Python + FlaskでMVC的なサンプルをつくったメモ。
MVC的な記事まとめ
ひとまずMVCについて言及されている記事をまとめ。
MVCはWikipediaが詳しい。
以下は調べた中でもわりと個人的にしっくりきた記事たち。
Web Applicationを綺麗に設計するためのMVACという考え方 - Dive into the Tech World!
Re: @kazuho: handlersocket plugin や mycached を使えば memcached は不要か、それとも使うべきケースがあるか。考察せよ [10点] - blog.nomadscafe.jp
Life is beautiful: Ruby on Railsの「えせMVC」の弊害
the { buckblogs :here }: Skinny Controller, Fat Model
共通して言われている気がするのが下記2点。守れば比較的キレイに設計できるかも。
- コントローラに処理を書きすぎない
- モデル = ORM としない
これはやっとけみたいなことが多いわりに絶対的なお約束がないMVC。
これはやっとけを全部守ってたらカオスになりそうなのでこの2点。
ModelでDBI, ORM, …という各機能をラップしてあげるイメージが一番しっくりきた。
これでごちゃごちゃしたソースコードが少しはスッキリしてくれるとありがたい。
Python + FlaskでMVC的なアプリ
上記記事を参考にしながらPython+FlaskでつくったMVC的構造のサンプルアプリをペタリ。
https://github.com/utahta/Flask-MVC-Pattern
projects/create で何かしらを登録し、projects/ で登録した何かしらを表示する至極簡素な機能付き。
以下、ソースコード(抜粋)。
コントローラ(myapp/controller/projects.py)でルーティング&入力値チェック。
from flask import Module, render_template, redirect, url_for, request from flaskext.wtf import Form, TextField, validators from myapp.model.projects import ProjectsModel projects = Module(__name__) @projects.route('/') def index(): model = ProjectsModel() # リスト表示 return render_template('projects/index.html', model=model) class CreateForm(Form): """ /projects/create 用のフォームクラス 入力値チェックも担う """ title = TextField(u'タイトル', [validators.Length(min=1, max=25)]) description = TextField(u'説明', [validators.Length(min=1, max=100)]) @projects.route('/create', methods=("GET", "POST")) def create(): model = ProjectsModel() form = CreateForm(request.form) if request.method == 'POST' and form.validate(): # チェック通ったらデータを保存し、/projects へリダイレクト model.save(form.title.data, form.description.data) return redirect(url_for('projects.index')) # 作成画面を表示 return render_template('projects/create.html', form=form)
Flask-WTFというFlaskの拡張機能を使ってフォームの値をチェック。
class CreateForm(Form) の部分。
モデル側に定義しようか一瞬迷うも、/createでしか使わないことを考えコントローラ側に定義。
プログラムがもっと大きくなったらまた考える。
モデル(myapp/model/projects.py)でデータ取得&保存。
from myapp import db from myapp.db.orm.projects import Projects class ProjectsModel(object): def get_entries(self): return db.session.query(Projects).all() def save(self, title, description): db.session.add(Projects(title, description)) db.session.commit()
ORMオブジェクトのProjectsをProjectsModelが操作。ラップップ。
ORMはSQLAlchemyを使用。
仕組みが単純なのでやってることも単純。
プログラムがもっと大きくなっても、データの一貫性保証とかもろもろここで処理する。
設計はデザイン
デザインはセンス。センスは経験。
ということで、以前つくったウェブアプリをFlaskで書き直して経験値ためる。
ついでにGAEに移植できたらいいかしらん。