再利用可能なDjangoアプリ開発 超訳
古いけど、これまたいい内容なので勝手に翻訳します。誤訳があれば是非ご指摘を。 しかもスライド資料の翻訳なので、流れがわかりづらい場合は是非、元動画を見ながらどうぞ。
- DjangoCon 2008 Reusable Apps
- http://www.youtube.com/watch?v=A-S0tqpPga4
4つの道筋
- ひとつのことをうまくやれ
- 複数アプリにすることを恐れるな
- 柔軟さを考慮して作れ
- 配布のことを考えて作れ
その1 「ひとつのことをうまくやれ」 -- UNIX 哲学
アプリケーション == カプセル化
ケーススタディ:ユーザー登録
仕様
- ユーザーがフォームから登録すると有効化されていないアカウントが作成される
- ユーザーがリンクを記載したメールを受信し、それをクリックして有効化する
- それだけ
いくつかの「シンプル」なことはそんなにシンプルじゃない。
仕様を疑ってかかる
この仕様を追加するべきか?
- このアプリケーションがすべきことは何?
- この仕様はそれに関係があるのか?
- 無い?なら追加すべきじゃないと思うよ。
django-registeration の一番の要求仕様: ユーザープロフィールだ
「ユーザー登録になければいけないことはなにか?」 -- 私
"No, You Can't Have a Pony"
じゃあ解決法は何?
django-profiles
- プロフィールの追加
- プロフィールの編集
- プロフィールの閲覧
- それだけ
その2 複数アプリにすることを恐れるな
一枚岩な考え方
- サイト全体がひとつの「アプリケーション」
- 再利用は後づけで
- 「メイン」アプリケーションにつなぎこむプラグイン開発をしがち
Django的な考え方
- アプリケーション == 機能単位
- サイト == いくつかのアプリケーション集合
- 自由に新しいアプリケーションに分割していく
この機能はこのアプリケーションが持つべきか?
- この機能は他の部分とは関係が無いか?
- 似たような機能が他のサイトでも必要になるだろうか?
- イエス?なら別のアプリに切り出すべきだね
ケーススタディ:ブログ
ブログが欲しいなー
- エントリとリンク
- タギング
- モデレート機能付きのコメント
- コンタクトフォーム
- 「About」ページ
- などなどなど
ということで
利点
- 仕様を書き直さずにすむ(?)
- 他のサイトにも簡単に使い回せる
urlpatterns += (‘’, (r’^contact/’, include(‘contact_form.urls’)), )
でもこんな時はどうすれば?
サイト特有の要望
- サイトAはメッセージを収集するだけのコンタクトフォームが欲しい
- サイトBのマーケティング部はいろいろな情報が欲しい
- サイトCは自動スパムフィルタに Akismet を使いたい
その3 柔軟さを考慮して作れ
良識として
- 分別のあるデフォルト値を
- 容易なオーバーライドを
- 何事も不変な状態にしない
フォームの処理
- form クラスを用意
- だけど好きな form を使用できるようにする
class SomeForm(forms.Form): ... def process_form(request, form_class=SomeForm): if request.method == ‘POST’: form = form_class(request.POST) ... else: form = form_class() ...
テンプレート
- デフォルトテンプレートを指定する
- だけど好きなテンプレートを使用できるようにする
def process_form(request, form_class=SomeForm, template_name='do_form.html'): ... return render_to_response(template_name, ...
フォームの処理
- サブミット成功時の処理後にリダイレクトしたい場合
- デフォルトのURLを用意する
- だけど好きな URL を使用できるようにする
def process_form(request, form_class=SomeForm, template_name='do_form.html', success_url='/foo/'): ... return HttpResponseRedirect(success_url)
その4 配布のことを考えて作れ
チュートリアルやったよね
- from mysite.polls.models import Poll
- mysite.polls.views.vote
- include('mysite.polls.urls')
- mysite.mysite.bork.bork.bork
プロジェクトとの結合は再利用性を低下させる
「プロジェクト」ってなんだ?
- settings モジュール
- ルート URLConf モジュール
- それだけ
ljworld.com
- worldonline.settings.ljworld
- worldonline.urls.ljworld
- そしてたくさんの再利用アプリ
再利用可能なアプリはこう見える
さて簡単
- distutils か setuptools を使ってパッケージをビルドできるようにして
- Cheese Shop(PyPI)に置く
- みんながダウンロードしてインストールできる
一般的なベストプラクティス
- 依存性について正直であるべし
- 可能なら Python2.3 向けに実装すべし
- release か trunck を使って、ドキュメントに書くべし(?)
- trunk を使用するなら、頻繁にアップデートすべし
テンプレートは大変
- テンプレートを提供することは、そのまま使えるので大きな利点になる
- だけどテンプレートをポータブルに作るのは大変(ブロック構造や継承、タグライブラリなど)
自分の場合は、あんまりデフォルトテンプレートは用意しないね。
どちらにせよ
- テンプレート名を記述するべし
- テンプレートコンテクストを記述するべし
ドキュメンテーション狂になるべし
最後にもう一度
- ひとつのことをうまくやれ
- 複数アプリにすることを恐れるな
- 柔軟さを考慮して作れ
- 配布のことを考えて作れ
いい例
- django-tagging (Jonathan Buchanan, http://code.google.com/p/django-tagging/)
- django-atompub (James Tauber, http://code.google.com/p/django-atompub/)
- コードホスティングサイトで "django" を検索
より詳細な情報
- django-hotclub (http://groups.google.com/group/django-hotclub/)
- Jannis Leidel の django パッケージ (http://code.google.com/p/django-reusableapps/)
- PyCon での Django スプリント