Django 開発初心者に送る 10 の Tips (超訳?)

実践的な DJango テクニック集として、凄くいい記事だったので、勝手に超訳してみました。

http://zeroandone.posterous.com/top-10-tips-to-a-new-django-developer

1. import にプロジェクト名を書かないこと

例えば "project3" というプロジェクトに "xyz" アプリケーションがある場合、次のようにはしないこと。

  from project3.xyz.models import Author


これではプロジェクトとアプリケーションの結びつきが強すぎて、以下の弊害がおこる。

  1. アプリケーションの再利用がしづらい
  2. 将来プロジェクト名を変えたくなっても変更が難しい


なので、このようにしよう。

  from xyz.models import Author

python パス上にある django プロジェクトならば、このように書ける。

2. MEDIA_ROOT と TEMPLATE_DIRS をハードコードしないこと

settings.py において、MEDIA_ROOT と TEMPLATE_DIRS を次のように書いてはいけない。

   TEMPLATE_DIRS = ( "/home/html/project/templates",)
   MEDIA_ROOT = "/home/html/project/appmedia/"


これではプロジェクトを別サーバに移動したり、別OSに変更する際に書き換えなければならなくなる。


これらの問題は次のテクニックを使うことで、簡単に避けることができる。

  SITE_ROOT = os.path.realpath(os.path.dirname(__file__))
  MEDIA_ROOT = os.path.join(SITE_ROOT, 'appmedia')
  TEMPLATE_DIRS = ( os.path.join(SITE_ROOT, 'templates'),)


自分はこのテクニックを Rob Hudson から学んだ。以下のリンクからより詳細な情報を得ることができる。

http://rob.cogit8.org/blog/2009/May/05/django-and-relativity-updated/

3. テンプレートに静的ファイルをハードコードしないこと

静的ファイル(JavaScript ファイルや css ファイル、画像など)のリンクを次のように書いてはいけない。

(MEDIA_URL を“/appmedia/”とする)

  <link rel="stylesheet" type="text/css" href="/appmedia/wysiwyg/jHtmlArea.css" />
  <script type="text/javascript" src="/appmedia/wysiwyg/jHtmlArea.js"></script>
  <script type="text/javascript" src="/appmedia/scripts/editor.js"></script>
  <script type="text/javascript" src="/appmedia/scripts/comments.js"></script>
  <script type="text/javascript" src="/appmedia/scripts/voting.js"></script>


上の書き方では、静的コンテンツを Amazon S3 を使って別サーバ(http://cdn.xyz.com としようか)に配置したい、なんていう場合に、全テンプレートの "/appmedia/" を http://cdn.xyz.com 書き換えなければいけなくなる。

うわぁ、超メンドくさい。


これはシンプルなテクニック、つまり "/appmedia/" のようなハードコーディングではなく、コンテクスト変数 {{MEDIA_URL}} を使うようにすることで、避けることができる

  <link rel="stylesheet" type="text/css" href="{{ MEDIA_URL }}wysiwyg/jHtmlArea.css" />
  <script type="text/javascript" src="{{ MEDIA_URL }}wysiwyg/jHtmlArea.js"></script>
  <script type="text/javascript" src="{{ MEDIA_URL }}scripts/editor.js"></script>
  
  <script type="text/javascript" src="{{ MEDIA_URL }}scripts/comments.js"></script>
  <script type="text/javascript" src="{{ MEDIA_URL }}scripts/voting.js"></script>


これで MEDIA_URL を "/appmedia/" から "http://cdn.xyz.com/" に変更すれば、全テンプレートに自動で反映される。いちいち全部のテンプレートを変更するなんていう超メンドくさいことはしなくていい。

どうやればコンテクスト変数を使えるの?

とっても簡単。RequestConext(request) を render_to_response に追加することで、便利なコンテクスト変数(ユーザーや取得ページなど)を、テンプレートに渡すことができる。

  return render_to_response("my_app/my_template.html", {'some_var': 'foo'},
  context_instance=RequestContext(request))

4. コアビジネスロジックを views に書かないこと!

コアビジネスロジックを views に書く(例えば銀行 X に総額 P を追加して、銀行 Y から P を引く、なんていうロジック)のはよろしくない。

なんで?
  1. コードをユニットテストできない
  2. コードを再利用できない
じゃあどこに書けばいい?

models かヘルパー関数に書くほうがいい。

基本的なロジックはどうする?

(モデルの)オブジェクトを検索や取得してきたり、リストを渡したり…なんていう、本当に基本的なロジックならば views に書いてもいいと思う。

5. 本番サーバに適用するとき、DEBUG=False (settings.py) に変更するのは面倒

ローカル環境を公開環境に移すとき、DEBUG を False にするのをよく忘れてしまう(DEBUG = False にすると利点が多い)し、退屈な作業だ。


これは以下のように、ホスト名をチェックして DEBUG 変数を設定するようにすればいい。

  import socket
  
  if socket.gethostname() == 'productionserver.com':
    DEBUG = False
  else:
    DEBUG = True

このテクニックを最初に指摘したのは Jokull だ。


より詳細な情報は:

http://nicksergeant.com/blog/django/automatically-setting-debug-your-django-app-based-server-hostname


別のテクニックとして、ローカル環境では、(DEBUG=Trueに設定した)もうひとつの settings ファイルを使う方法もある。

  #Filename settings_debuy.py
  #It contains all variables from settings and it overrides the DEBUG variable to True
  #we use settings_debug.py to run the server locally python manage.py runserver settings=settings_debug.py
  
  from settings import *
  DEBUG = True
  
  #you can also add other things which helps you to do the debugging easily
  #like Debug toolbar etc...

6. サードパーティ製のアプリケーションに依存するテンプレートタグは一度だけ load する

サードパーティ製アプリケーションのテンプレートタグを使うには、次のようにテンプレート内で load する必要がある。

  {% load template_tags %}


サードパーティ製のテンプレートタグを利用するテンプレート全てに同様の記述をする必要があるが、これは DRY の原理に反する。これを改善しよう。

  from django import template
  template.add_to_builtins('project.app.templatetags.custom_tag_module')

このコードを、起動時に読み込まれるファイル(settings.py や urls.py、各アプリの models.py など)のどれかに書いておくだけ。


上記コードが起動時にテンプレートタグを読み込んでくれるので、 {% load template_tags %} を使わなくても、好きなテンプレートでそのテンプレートタグを使うことができる。

7. Urls.py

project/urls.py に全 URL を書かない

例えば

  urlpatterns = patterns('',
  url(r'^askalumini/question/$','.....registerInstitution',name='iregister'),
  url(r'^askalumin/answer/$','someview.....',name='newmemberurl'),
  url(r'^institution/member/$','someview.....',name="dashboardurl"),
  url(r'^institution/faculty/$','editInstitute',name="editinstituteurl"),
  url(r'^memeber/editprofile/$','editProfile',name="editprofileurl"),
  url(r'^member/changepassword/$','changePassword',name="changepasswordurl"),
  url(r'^member/forgotpassword/$','forgotPassword',name="forgotpasswordurl"),
  url(r'^member/changepicture/$','changePicture',name="changepictureurl"),
  url(r'^member/logout/$','memeberlogout',name="logouturl"), ,
  )


代わりに次のように、複数アプリケーションに分離する(プロジェクトの /urls.py に記述する)。
これによって、アプリケーションを変更作業なしに、異なるプロジェクトで再利用することができる。

  urlpatterns = patterns('',
  # Example:
  (r'^$', include('institution.urls')),
  (r'^institution/', include('institution.urls')),
  (r'^askalumini/', include('askalumini.urls')),
  (r'^member/', include('member.urls')),
  )


それから urls.py を各アプリケーションに作成し、対応する URL を追加する(以下は askalumini アプリを例として挙げている)。

  urlpatterns = patterns('askalumini.views',
  url(r'^$','askHome',name='askaluminiurl'),
  url(r'^questions/(?P<questionno>\d+)/$','displayQuestion',name='askquestiondisplay'),
  url(r'^askquestions/$','askQuestion',name='askquestionurl'),
  url(r'^postcomment/$','postComment',name="askquestioncomment")
URL の定義には url 関数を使用する

URL を定義するのに、URL に名前を付けられる url 関数を使用しているのに気付いたと思う。上で定義した全 URLには、最後に URL 名を指定している(name="....." のように)。この名前によって、views や templates、そして models において、URL のハードコーディングをしないで済むような、効果的な指定ができるようになる。


各アプリにおいて URL 名のユニークさを保つために、URL の命名は "" のような命名規約に沿うようにしている(上のコード参照)。

URL をハードコードしない

なぜって?


urls.py の URL 構造を変更する場合、URL をハードコーディングした全ての箇所を書き換える必要が出てくるからだ。(超メンドくさい…)

views.py では

以下のように URL をハードコードする代わりに、

  HttpResponseRedirect("/askalumini/questions/54")


URL 名を用いて reverse ルックアップ関数を使用して URL を生成する。

  from django.core.urlresolvers import reverse
  HttpResponseRedirect(reverse('askquestiondisplay',kwargs={'questionno':q.id}))
models.py では

絶対 URL を生成するために、models.py では reverse ルックアップ関数に加え、models.permalink decorator を使用できる。

  @models.permalink
  def get_absolute_url(self):
    return ('profileurl2',(),{'userid': self.user.id})


このデコレータでも、URL を生成するために URL 名を使用する。

templates.py では

いろいろと不便なハードコーディグをする代わりに、 url タグ を使うことで、URL 名を用いて URL を生成することができる。

  {% url askquestiondisplay 345 %}
  <a href="{% url askquestiondisplay 345 %}"> Ask Question </a>

8. デバッグ

a. django-debug-toolbar を使うことで、以下のような情報を取得できる
  1. どれくらいの数の SQL 文が実行されたか?トータルタイムは?
  2. テンプレート名、ロギング、クッキー/セッション情報、などなど


debug-toolbar のより詳細な情報は以下のリンク先で確認できる。

http://github.com/robhudson/django-debug-toolbar/tree/master

b. Werkzeug デバッガを使えば、エラー画面で Python シェルを開くことができ、迅速なデバッグ作業に役立つ。

詳細な情報は以下のリンクから。

http://blog.dpeepul.com/2009/07/14/python-shell-right-on-the-django-error-page/

c. デバッグ作業に pdb を使う。

詳細はこちら。

http://ericholscher.com/blog/2008/aug/31/using-pdb-python-debugger-django-debugging-series-/

9. 可能なら利用できるように Pinax について知っておく

Django を使う最大の利点のひとつとして、アプリケーションの再利用性がある。

Django は他のフレームワークのような一枚岩な設計を志向せずに、再利用性を促進させている。これは、他のフレームワークではなく Django を選ぶ際の重要な理由のひとつであり、Pinax はそのような設計方針に対する成果のひとつだ。


Pinax って何?


近年では、世界のどのウェブサイトでも登録、OpenIDのサポート、グループ、ユーザープロフィールなどといった機能が要求される。ほとんどのサイトで、これらの機能のロジックを実装しなければならない。独立した再利用可能な機能を提供するプラットフォーム(django のプロジェクト)があり、またその上で開発してもらえれば、これらの機能は、様々なサイト間で再利用することができる。そのようなプラットフォームは、迅速なウェブサイト構築を可能にし、開発者は、彼らのサイト独自の部分の開発に注力することができる。


Pinax はそんな再利用可能なアプリケーションを集めた(Django の)プラットフォームだ。Pinax は次のような再利用可能な機能やアプリケーションを提供する。

  1. openid サポート
  2. (vCard, Google, Yahoo などからの)連絡先のインポート
  3. 通知フレームワークなどなど… より詳細な情報はこちら http://pinaxproject.com/


Pinax は James Tauber による強力なアイデアだ。可能なら是非使ってみてほしい。迅速なウェブアプリケーションの構築の助けになるはずだ。


より詳細な情報はこちら

http://uswaretech.com/blog/2009/03/create-a-new-social-networking-site-in-few-hours-using-pinax-platform-django/

10. 知っておくべきサードパーティ製アプリケーション

使うべきサードパーティ製アプリケーションがいくつかある。

1. マイグレーション

スキーマやデータのマイグレーションはどうしてる?


syncdb するよね。


最初はモデルの設計がデータベースに反映される。


でも何時間、何日か経ったら…


モデルにフィールドを追加したり、削除したり、設計を変更しなければならなくなる。
変更するよね。ここで、どうやってこの変更をデータベースに反映させるかが重大な問題になる。
取れる方法としては、

  • もう一度 syncdb する(メンドくさい)
  • 手動で alter 文を DB に発行する(メンドくさい)


このようにデータベースをある状態から別の状態に変更することをマイグレーションと呼ぶ。このマイグレーションを楽にしてくれる、いくつかのサードパーティアプリケーションがある。

  • django-evolutions (簡単に使えて、自動で全部やってくれるけど、頑丈じゃない)
  • South (より強固だけど、ちょっと使い方を覚える必要がある)
2. テンプレート

Django のテンプレートは、制限がキツすぎると思ったら、次のようなものもある。

  1. template-utils (テンプレートタグやユーティリティよりも、テンプレートの機能を向上)
  2. Jinja (Django テンプレートと同じシンタックスを採用し、プロジェクトのプラグインとして使える、そしてより柔軟なロジック記述が特徴の、サードパーティのテンプレートシステム)
3. その他

1. django command extensions 次のようなお役立ちコマンドラインを提供してくれる

    1. 全モデルをロードしてくれる shell_plus
    2. Werkzeug デバッガを組み込んだ runserver_plus
    3. 上司に見せるためのモデル図生成

などなど。


より詳しい情報はこちら

http://ericholscher.com/blog/2008/sep/12/screencast-django-command-extensions/


2. Sorl はサムネイルを生成してくれる

など


他のリソースはこちら

  1. http://stackoverflow.com/questions/550632/favorite-django-tips-features