Django の概要
| revision-up-to: | 5832 (0.97pre SVN) |
|---|
Django は変転の激しいニュースルーム環境で開発された経緯から、よくある Web 開発タスクを迅速かつ簡単化するように設計されました。ここでは Django に よるデータベース中心の Web アプリケーション開発をざっと見てみましょう。
このドキュメントの目的は、 Django の技術的な仕様について述べ、どのように動 作するかを理解してもらうことにあり、チュートリアルやリファレンス用ではあり ません。Django のプロジェクトを作成する準備ができているなら、詳しく書かれた ドキュメント を参照してください。
モデルの設計
Django はデータベースなしでも使えます。とはいえ、 Django にはオブジェクト- リレーショナルマッパが付属していて、 Python コードでデータベースのレイアウ ト記述できるようになっています。
Django のデータ-モデルシンタクスはモデルを表現するための色々な方法を提供し ています。この API には、この 2 年データベーススキーマ問題を解決してきた実 績があります。簡単な例を示しましょう:
class Reporter(models.Model):
full_name = models.CharField(max_length=70)
def __unicode__(self):
return self.full_name
class Article(models.Model):
pub_date = models.DateTimeField()
headline = models.CharField(max_length=200)
article = models.TextField()
reporter = models.ForeignKey(Reporter)
def __unicode__(self):
return self.headline
モデルのインストール
次に、Django コマンドラインユーティリティを実行し、データベース上にテーブル を自動的に生成します。
django-admin.py syncdb
syncdb コマンドは利用可能な全てのモデルを探し、まだ作成されていないテー ブルがあれば作成します。
自動生成される API で楽しむ
インストールだけで、制約のない充実した Python API を使って自分のデータ にアクセスできるようになります。API はオンザフライで生成され、コードを作成 する必要はありません:
>>> from mysite.models import Reporter, Article
# まだシステム上に Reporter はひとつもありません。
>>> Reporter.objects.all()
[]
# 新しい Reporter を作成します。
>>> r = Reporter(full_name='John Smith')
# オブジェクトをデータベースに保存します。
# 明示的に save() を呼ばねばなりません。
>>> r.save()
# オブジェクトに ID が割り当てられました。
>>> r.id
1
# 作成した Reporter はデータベース上にあります。
>>> Reporter.objects.all()
[John Smith]
# 各フィールドは Python オブジェクトの属性として表現されています。
>>> r.full_name
'John Smith'
# Django は充実したデータベース検索 API を提供しています。
>>> Reporter.objects.get(id=1)
John Smith
>>> Reporter.objects.get(full_name__startswith='John')
John Smith
>>> Reporter.objects.get(full_name__contains='mith')
John Smith
>>> Reporter.objects.get(id=2)
Traceback (most recent call last):
...
DoesNotExist: Reporter does not exist for {'id__exact': 2}
# Article を作成します。
>>> from datetime import datetime
>>> a = Article(pub_date=datetime.now(), headline='Django is cool',
... article='Yeah.', reporter_id=1)
>>> a.save()
# これで Article はデータベースに入りました。
>>> Article.objects.all()
[Django is cool]
# Article オブジェクトから、リレーションを張っている Reporter にアクセ
# スできる API を使えるようになります。
>>> r = a.reporter
>>> r.full_name
'John Smith'
# 逆も可能です: Reporter オブジェクトから Article オブジェクトにアクセスできます。
>>> r.article_set.all()
[Django is cool]
# API は必要に応じてリレーションを辿ります。背後では効率的に JOIN を
# 行います。
# "John" ではじまる Reporter の全ての Article を検索してみましょう。
>>> Article.objects.filter(reporter__full_name__startswith="John")
[Django is cool]
# 属性値を変更して save() すればオブジェクトを変更できます。
>>> r.full_name = 'Billy Goat'
>>> r.save()
# delete() でオブジェクトを削除できます。
>>> r.delete()
動的な admin インタフェース: 足場 (scaffold) ではなく完成品 (whole house)
モデルを定義したら、 Django は玄人向きの実運用に耐える管理インタフェース (admin interface) を自動的に生成します。 admin インタフェースとは、認証をパ スしたユーザがオブジェクトを追加、変更、削除できる Web サイトです。 admin インタフェースの作成は簡単で、モデルクラスに一行書き加えるだけです:
class Article(models.Model):
pub_date = models.DateTimeField()
headline = models.CharField(max_length=200)
article = models.TextField()
reporter = models.ForeignKey(Reporter)
class Admin: pass
サイトの編集はスタッフ、顧客、もしくはあなた自身の手で行われるものであり、 コンテンツの管理だけのためにバックエンドインタフェースを作りたくはない、 という思想がここにはあります。
作者たちが Django アプリケーションを作成するときの典型的なワークフローは、 モデルを作成し、 admin サイトを組み上げてできるだけ早期に立ち上げ、スタッフ (や顧客) がデータを投入できるようにしておいてから、データを公開するための方 法を開発してゆくというものです。
自由な URL 設計
すっきりとして洗練された URL スキームは、高品質な Web アプリケーションを実 現する上で重要な要素です。 Django は美しい URL の設計を助け、 .php や .asp のようなお粗末な制約を URL に課しません。
特定のアプリケーション用の URL を設計するには、 URLconf と呼ばれる Python モジュールを一つ作成します。 URLconf はいわばアプリケーションの目次にあたり、 URL のパターンを Python のコールバック関数に対応づけています。 URLconf はま た、 URL を Python コードと脱カップリングする働きを持っています。
Reporter/Article の例では、 URLconf は以下のようになります:
from django.conf.urls.defaults import *
urlpatterns = patterns('',
(r'^articles/(\d{4})/$', 'mysite.views.year_archive'),
(r'^articles/(\d{4})/(\d{2})/$', 'mysite.views.month_archive'),
(r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'mysite.views.article_detail'),
)
上のコードは簡単な正規表現で書かれた URL を Python コールバック関数 (ビュー: view) に対応づけています。正規表現の中で丸括弧を使い、 URL から値を「取り込 み」ます。ユーザがあるページをリクエストすると、 Django は全ての正規表現に わたって順に調べてゆき、最初に URL にマッチするパターンで止まります。 (マッ チする正規表現がなければ Django は独自の 404 ビューを呼び出しします)。 正規 表現をロード時にコンパイルしておくので、この処理は極めて高速です。
正規表現が URL にマッチすると、 Django は指定されているビューを import して 呼び出します。ビューは単純な Python の関数です。各ビューにはリクエストオブ ジェクトが渡されます。リクエストオブジェクトにはリクエストのメタデータと、 正規表現で取り込んだ値が渡されます。
例えば、ユーザが "/articles/2005/05/39323/" という URL をリクエストすると、 Django は mysite.news.views.article_detail(request, '2005', '05', '39323') のような関数呼び出しを行います。
ビューの自作
各ビュー (view) には二つの役割があります: 一つはリクエストされたページのコ ンテンツを含む HttpResponse オブジェクトを返すこと、もう一つは Http404 のような例外の送出です。それ以外の処理はユーザ次第です。
一般的に、ビューはパラメタに従ってデータベースからデータを取り出し、テンプ レートをロードして、取り出したデータでテンプレートをレンダリングします。 上の year_archive のビューを例に示しましょう:
def year_archive(request, year):
a_list = Article.objects.filter(pub_date__year=year)
return render_to_response('news/year_archive.html',
{'year': year, 'article_list': a_list})
この例ではいくつかの強力な機能を備えながらも、非プログラマが使いこなせる 程度に十分単純な、 Django のテンプレートシステムを使っています。
テンプレートの設計
上のコードでは news/article_detail.html という名前のテンプレートをロー ドしています。
Django にはテンプレート検索パスという概念があり、テンプレートが冗長になるの を防いでいます。 Django の設定で、テンプレートを探すディレクトリのリストを 設定しておきます。あるディレクトリにテンプレートが見つからなければ、Django は次のディレクトリ、また次のディレクトリとテンプレートを探します。
さて、 news/article_detail.html が見つかったとしましょう。テンプレート は以下のように書かれています:
{% extends "base.html" %}
{% block title %}Articles for {{ year }}{% endblock %}
{% block content %}
<h1>Articles for {{ year }}</h1>
{% for article in article_list %}
<p>{{ article.headline }}</p>
<p>By {{ article.reporter.full_name }}</p>
<p>Published {{ article.pub_date|date:"F j, Y" }}</p>
{{ article.article }}
{% endfor %}
{% endblock %}
変数は二重の波括弧で囲まれています。 {{ article.headline }} は、 「article の headline という属性の出力」を表しています。とはいえ、ドット表 記は属性の検索に使われるだけではありません。辞書の検索や、インデクス指定、 関数呼び出しも行えます。
{{ article.pub_date|date:"F j, Y" }} で、 Unix スタイルの「パイプ」 (文字 "|") を使っていることに注意して下さい. これはテンプレートフィルタ と呼ばれ、変数の値にフィルタをかけるためのものです。この例では、フィルタに よって Python の datetime オブジェクトを指定の形式にフォーマットしています (PHP の date 関数に似ていますね。そう、これは PHP の便利なところです)。
フィルタは好きなだけ連鎖させられます。カスタムのフィルタも実装できます。 カスタムのテンプレートタグを設計でき、背後で自作の Python コードを実行でき ます。
最後に、Django にはテンプレートの継承という概念があります: 継承を宣言してい るのは {% extends "base.html" %} の部分です。このタグは「まず 'base.html' というテンプレートをロードせよ。このテンプレートにはいくつかの ブロックが定義されているが、それらのブロックの中身を以下のブロック定義で埋 めよ」という命令です。要するに、テンプレートを継承すると、各テンプレートご とに固有の定義だけを記述すればよくなり、テンプレート間の冗長性が劇的に減る のです。
”base.html” テンプレートは以下のようになります:
<html>
<head>
<title>{% block title %}{% endblock %}</title>
</head>
<body>
<img src="sitelogo.gif" alt="Logo" />
{% block content %}{% endblock %}
</body>
</html>
このテンプレートはサイトのルック & フィール (とサイトのロゴ) を定義するだけ の極度に単純化されています。また、子テンプレートで埋めるための「穴」を提供 しています。これによって、ベーステンプレート一つを変更するだけでサイト全体 のデザインを簡単に変更できるようになります。
また、子テンプレートを変えずにベーステンプレートだけを変えた複数バージョン のサイトも作成できます。 Django の作者たちはこのテクニックを使い、新しい テンプレートを作成するだけで携帯電話向けのまったく見栄えの違うサイトを 作成してきました。
他のシステムを使いたければ、必ずしも Django のテンプレートシステムを使う必 要はないということに注意してください。 Django のテンプレートシステムは Django のモデルレイヤと部分的にしっかり組み合わさっていますが、絶対に使わね ばならないということではありません。さらに言えば、 Django のデータベース API を使う必然性もありません。別のデータベース抽象化レイヤを使っても構いま せんし、 XML ファイルやディスク上のファイルを読み込んでも構いません。何でも やりたいことをできるのです。Django の構成要素 -- モデル、ビュー、テンプレー ト -- は、互いに切り離して利用できるのです。
これらはほんの一部にすぎません
以上、 Django の機能についてざっと紹介してきました。 Django は他にもまだま だ便利な機能を備えています:
- memcached などのバックエンドを組み込んだキャッシュフレームワーク。
- 小さな Python クラスを書くだけで簡単に RSS や Atom フィードを生成でき る 配信フィードフレームワーク 。
- 自動生成される admin のセクシーな機能の数々。ここで紹介したのはほんの 表層の一部でしかありません。
次は、あなたが Django をダウンロード して、 チュートリアル を読み、 コミュニティ に参加する番です。ご精読ありがとうございました!