Django の概要

revision-up-to:17812 (1.4)

Django は変転の激しいニュースルーム環境で開発された経緯から、よくある Web 開発タスクを迅速かつ簡単化するように設計されました。ここでは Django による データベース中心の Web アプリケーション開発をざっと見てみましょう。

このドキュメントの目的は、 Django の技術的な仕様について述べ、どのように動 作するかを理解してもらうことにあり、チュートリアルやリファレンス用ではあり ません。(とはいえ、チュートリアルもリファレンスも別に用意していますよ!) プロジェクトを作成する準備ができたら、 チュートリアルをはじめる か、 より詳細なドキュメントに読み進んで みてください。

モデルの設計

Django はデータベースなしでも使えます。とはいえ、 Django にはオブジェクト- リレーショナルマッパが付属していて、 Python コードでデータベースのレイアウ ト記述できるようになっています。

Django の データモデルシンタクス はモデルを表現 するための色々な方法を提供しています。この API には、 2 年間にわたって様々 なデータベーススキーマの問題を解決してきた実績があります。 mysite/news/models.py ファイル内に保存されるような、簡単な例を示しまし ょう:

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)
    content = models.TextField()
    reporter = models.ForeignKey(Reporter)

    def __unicode__(self):
        return self.headline

モデルのインストール

次に、Django コマンドラインユーティリティを実行し、データベース上にテーブル を自動的に生成します:

manage.py syncdb

syncdb コマンドは利用可能な全てのモデルを探し、まだ作成されてい ないテーブルがあれば作成します。

自動生成される API で楽しむ

これだけで、制約のない充実した Python API を使っ て自分のデータにアクセスできます。API はオンザフライで生成され、コードを作 成する必要はありません:

.. # Import the models we created from our "news" app

# "news" アプリで作成したモデルを import します。
>>> from news.models import Reporter, Article

.. # No reporters are in the system yet.

# まだシステム上に Reporter はひとつもありません。
>>> Reporter.objects.all()
[]

.. # Create a new Reporter.

# 新しい Reporter を作成します。
>>> r = Reporter(full_name='John Smith')

.. # Save the object into the database. You have to call save() explicitly.

# オブジェクトをデータベースに保存します。
# 明示的に save() を呼ばねばなりません。
>>> r.save()

.. # Now it has an ID.

# オブジェクトに ID が割り当てられました。
>>> r.id
1

.. # Now the new reporter is in the database.

# 作成した Reporter はデータベース上にあります。
>>> Reporter.objects.all()
[<Reporter: John Smith>]

.. # Fields are represented as attributes on the Python object.

# 各フィールドは Python オブジェクトの属性として表現されています。
>>> r.full_name
'John Smith'

.. # Django provides a rich database lookup API.

# Django は充実したデータベース検索 API を提供しています。
>>> Reporter.objects.get(id=1)
<Reporter: John Smith>
>>> Reporter.objects.get(full_name__startswith='John')
<Reporter: John Smith>
>>> Reporter.objects.get(full_name__contains='mith')
John Smith
>>> Reporter.objects.get(id=2)
Traceback (most recent call last):
    ...
DoesNotExist: Reporter matching query does not exist.

.. # Create an article.

# Article を作成します。
>>> from datetime import datetime
>>> a = Article(pub_date=datetime.now(), headline='Django is cool',
...     content='Yeah.', reporter_id=1)
>>> a.save()

.. # Now the article is in the database.

# これで Article はデータベースに入りました。
>>> Article.objects.all()
[<Article: Django is cool>]

.. # Article objects get API access to related Reporter objects.

# Article オブジェクトから、リレーションを張っている Reporter にアクセ
# スできる API を使えるようになります。
>>> r = a.reporter
>>> r.full_name
'John Smith'

.. # And vice versa: Reporter objects get API access to Article objects.

# 逆も可能です: Reporter オブジェクトから Article オブジェクトにアクセスできます。
>>> r.article_set.all()
[<Article: Django is cool>]

.. # The API follows relationships as far as you need, performing efficient
   # JOINs for you behind the scenes.
   # This finds all articles by a reporter whose name starts with "John".

# API は必要に応じてリレーションを辿ります。背後では効率的に JOIN を
# 行います。
# "John" ではじまる Reporter の全ての Article を検索してみましょう。
>>> Article.objects.filter(reporter__full_name__startswith="John")
[<Article: Django is cool>]

.. # Change an object by altering its attributes and calling save().

# 属性値を変更して save() すればオブジェクトを変更できます。
>>> r.full_name = 'Billy Goat'
>>> r.save()

.. # Delete an object with delete().

# delete() でオブジェクトを削除できます。
>>> r.delete()

作業場 (scaffold) ではなく完成品 (whole house) の、動的な管理インタフェース

モデルを定義したら、 Django は玄人向きの実運用に耐える 管理インタフェー ス (admin interface) を自動的に生成します。 管理インタ フェースとは、認証をパスしたユーザがオブジェクトを追加、変更、削除できる Web サイトです。管理インタフェースの作成は簡単で、モデルクラスを admin に追 加するだけです:

.. # In models.py...

# models.py には以下のように書きます

from django.db import models

class Article(models.Model):
    pub_date = models.DateTimeField()
    headline = models.CharField(max_length=200)
    content = models.TextField()
    reporter = models.ForeignKey(Reporter)

.. # In admin.py in the same directory...

# 同じディレクトリの admin.py には以下のように書きます

import models
from django.contrib import admin

admin.site.register(models.Article)

サイトの編集はスタッフ、顧客、もしくはあなた自身の手で行われるものであり、 コンテンツの管理だけのためにバックエンドインタフェースを作りたくはない、 という思想がここにはあります。

作者たちが 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 import patterns, url, include

urlpatterns = patterns('',
    (r'^articles/(\d{4})/$', 'news.views.year_archive'),
    (r'^articles/(\d{4})/(\d{2})/$', 'news.views.month_archive'),
    (r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'news.views.article_detail'),
)

上のコードは簡単な正規表現で書かれた URL を Python コールバック関数 (ビュー: view) に対応づけています。正規表現の中で丸括弧を使い、 URL から値を「取り込 み」ます。ユーザがあるページをリクエストすると、 Django は全ての正規表現に わたって順に調べてゆき、最初に URL にマッチするパターンで止まります。 (マッ チする正規表現がなければ Django は独自の 404 ビューを呼び出しします)。 正規 表現をロード時にコンパイルしておくので、この処理は極めて高速です。

正規表現が URL にマッチすると、 Django は指定されているビューを import して 呼び出します。ビューは単純な Python の関数です。各ビューにはリクエストオブ ジェクトが渡されます。リクエストオブジェクトにはリクエストのメタデータと、 正規表現で取り込んだ値が渡されます。

例えば、ユーザが “/articles/2005/05/39323/” という URL をリクエストすると、 Django は 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/year_archive.html が見つかったとしましょう。テンプレート は以下のように書かれています:

{% extends "base.html" %}

{% block title %}{{ year }}年の記事{% endblock %}

{% block content %}
<h1>{{ year }}年の記事</h1>

{% for article in article_list %}
<p>{{ article.headline }}</p>
<p>By {{ article.reporter.full_name }}</p>
<p>作成日: {{ 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 は他にもまだま だ便利な機能を備えています:

  • 自動生成される admin のセクシーな機能の数々。ここで紹介したのはほんの 表層の一部でしかありません。

次は、あなたが Django をダウンロード して、 チュートリアル を読み、 コミュニティ に参加す る番です。ご精読ありがとうございました!