Django の概要¶
Django は変転の激しいニュースルーム環境で開発された経緯から、よくある Web 開発タスクを迅速かつ簡単化するように設計されました。ここでは Django による データベースを使った Web アプリケーション開発をざっと見てみましょう。
このドキュメントの目的は、 Django の技術的な仕様について述べ、どのように動作するかを理解してもらうことにあり、チュートリアルやリファレンスではあり ません。 (とはいえ、チュートリアルもリファレンスも別に用意していますよ!) プロジェクトを作成する準備ができたら、 チュートリアルを始める ことも、 より詳細なドキュメントを読む こともできます。
モデルの設計¶
データベースなしで Django を使うこともできますが、 Django には Python コードでデータベースのレイアウトを記述した オブジェクトリレーショナルマッパー (object-relational mapper) が付属しています。
データモデル構文 ではモデルを表現するさまざまな方法が提供されています。これまでのところ、長年におけるデータベーススキーマの問題を解決してきた実績があります。 簡単な例を示しましょう:
from django.db import models
class Reporter(models.Model):
full_name = models.CharField(max_length=70)
def __str__(self):
return self.full_name
class Article(models.Model):
pub_date = models.DateField()
headline = models.CharField(max_length=200)
content = models.TextField()
reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)
def __str__(self):
return self.headline
モデルのインストール¶
次に、データベーステーブルを自動で作成する Django のコマンドラインユーティリティを実行します:
$ python manage.py migrate
...\> py manage.py migrate
migrate
コマンドは利用できるモデルを全て見て、テーブルが既に存在していない場合にはデータベースにテーブルを作成し、必要に応じて より強力なスキーマの制御 を提供します。
自動生成される API で楽しむ¶
これだけで、制約のない充実した Python API を使って自分のデータにアクセスできます。API はオンザフライで生成され、コードを作成する必要はありません:
# Import the models we created from our "news" app
>>> from news.models import Article, Reporter
# No reporters are in the system yet.
>>> Reporter.objects.all()
<QuerySet []>
# Create a new Reporter.
>>> r = Reporter(full_name='John Smith')
# Save the object into the database. You have to call save() explicitly.
>>> r.save()
# Now it has an ID.
>>> r.id
1
# Now the new reporter is in the database.
>>> Reporter.objects.all()
<QuerySet [<Reporter: John Smith>]>
# Fields are represented as attributes on the Python object.
>>> r.full_name
'John Smith'
# Django provides a rich database lookup 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')
<Reporter: John Smith>
>>> Reporter.objects.get(id=2)
Traceback (most recent call last):
...
DoesNotExist: Reporter matching query does not exist.
# Create an article.
>>> from datetime import date
>>> a = Article(pub_date=date.today(), headline='Django is cool',
... content='Yeah.', reporter=r)
>>> a.save()
# Now the article is in the database.
>>> Article.objects.all()
<QuerySet [<Article: Django is cool>]>
# Article objects get API access to related Reporter objects.
>>> r = a.reporter
>>> r.full_name
'John Smith'
# And vice versa: Reporter objects get API access to Article objects.
>>> r.article_set.all()
<QuerySet [<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".
>>> Article.objects.filter(reporter__full_name__startswith='John')
<QuerySet [<Article: Django is cool>]>
# Change an object by altering its attributes and calling save().
>>> r.full_name = 'Billy Goat'
>>> r.save()
# Delete an object with delete().
>>> r.delete()
作業場 (scaffold) ではなく完成品 (whole house) の、動的な admin インタフェース¶
モデルを定義したら、 Django は玄人向きの実運用に耐える 管理インタフェー ス を自動的に生成します。 このインタフェースは、認証をパスしたユーザがオブジェクトを追加、変更、削除できる Web サイトです。管理インタフェースの作成は簡単で、モデルクラスを admin サイトに追加するだけです:
from django.db import models
class Article(models.Model):
pub_date = models.DateField()
headline = models.CharField(max_length=200)
content = models.TextField()
reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)
from django.contrib import admin
from . import models
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.urls import path
from . import views
urlpatterns = [
path('articles/<int:year>/', views.year_archive),
path('articles/<int:year>/<int:month>/', views.month_archive),
path('articles/<int:year>/<int:month>/<int:pk>/', views.article_detail),
]
上のコードは、 URL パスを Python のコールバック関数("views")にマッピングしています。 パス文字列は、パラメータタグを使用して URL から値を取得します。 ユーザがページをリクエストすると、Django は各パスを順番に実行し、要求された URL に最初に一致したパスで停止します。 (それらのどれとも一致しない場合、Django は特殊なケースである404ビューを呼び出します。)パスはロード時に正規表現にコンパイルされるので、これらは非常に高速に動作します。
URL パターンの1つが一致すると、Django は与えられたビューを呼び出します。これは Python の関数です。 各ビューは、リクエストのメタデータを含むリクエストオブジェクトと、パターンで捉えられた値を渡します。
例えば、ユーザが "/articles/2005/05/39323/" という URL をリクエストすると、 Django は news.views.article_detail(request, year=2005, month=5, pk=39323)
のような関数呼び出しを行います。
ビューの自作¶
各ビュー (view) には二つの役割があります: 一つはリクエストされたページのコ ンテンツを含む HttpResponse
オブジェクトを返すこと、もう一つは Http404
のような例外の送出です。それ以外の処理はユーザ次第です。
一般的に、ビューはパラメーターに従ってデータベースからデータを取り出し、テンプレートをロードして、取り出したデータでテンプレートをレンダリングします。 上の year_archive
のビューを例に示しましょう:
from django.shortcuts import render
from .models import Article
def year_archive(request, year):
a_list = Article.objects.filter(pub_date__year=year)
context = {'year': year, 'article_list': a_list}
return render(request, 'news/year_archive.html', context)
この例では Django の テンプレートシステム を使っ ています。テンプレートシステムは、強力な機能をいくつも備えながらも、非プロ グラマが使いこなせる程度に簡単な仕組みです。
テンプレートを設計する¶
上のコードでは news/article_detail.html
という名前のテンプレートをロー ドしています。
Django はテンプレートの重複を最小限にする為に、テンプレートの検索パスを持っています。Djangoの設定ファイルの中で、テンプレートをチェックする DIRS
にディレクトリのリストを指定します。最初のディレクトリにテンプレートが存在しかった場合、2番目をチェックし、以降も同様にチェックが続きます。
さて、 news/year_archive.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>
{% endfor %}
{% endblock %}
変数は二重の波括弧で囲まれています。 {{ article.headline }}
は、「article の headline という属性の出力」を表しています。とはいえ、ドット表記は属性の検索に使われるだけではありません。辞書の検索や、インデクス指定、関数呼び出しも行えます。
{{ article.pub_date|date:"F j, Y" }}
で、 Unix スタイルの「パイプ」 (文字 “|”) を使っていることに注意して下さい。これはテンプレートフィルターと呼ばれ、変数の値にフィルターをかけるためのものです。この例では、フィルタによって Python の datetime オブジェクトを指定の形式にフォーマットしています (PHP の date 関数に似ていますね) 。
フィルターはいくつでも好きなだけ繋げることが出来ます。また、独自の Python コードを実行する カスタムテンプレートフィルタ や カスタムテンプレートタグ を書くことも出来ます。
最後に、 Django にはテンプレートの継承という概念があります。 継承を宣言しているのは {% extends "base.html" %}
の部分です。このタグは「まず ‘base’ というテンプレートをロードせよ。このテンプレートにはいくつかのブロックが定義されているが、それらのブロックの中身を以下のブロック定義で埋めよ」という命令です。要するに、テンプレートを継承すると、各テンプレートごとに固有の定義だけを記述すればよくなり、テンプレート間の冗長性が劇的に減るのです。
ここでよくある“base.html” テンプレートで、 静的ファイルの配信 を含む例をあげます:
{% load static %}
<html>
<head>
<title>{% block title %}{% endblock %}</title>
</head>
<body>
<img src="{% static "images/sitelogo.png" %}" alt="Logo">
{% block content %}{% endblock %}
</body>
</html>
このテンプレートはサイトのルック & フィール (とサイトのロゴ) を定義するだけ にまで、極度に単純化されています。また、子テンプレートで埋めるための「穴」 を提供しています。これによって、ベーステンプレート一つを変更するだけでサイ ト全体のデザインを簡単に変更できます。
また、子テンプレートを変えずにベーステンプレートだけを変えた複数バージョン のサイトも作成できます。 Django の作者たちはこのテクニックを使い、新しいテンプレートを作成するだけでモバイル向けのまったく見栄えの違うサイトを作成してきました。
他のシステムを使いたければ、必ずしも Django のテンプレートシステムを使う必 要はないということに注意してください。 Django のテンプレートシステムは Django のモデルレイヤと部分的にしっかり組み合わさっていますが、絶対に使わねばならないということではありません。さらに言えば、 Django のデータベース API を使う必然性もありません。別のデータベース抽象化レイヤを使っても構いま せんし、 XML ファイルやディスク上のファイルを読み込んでも構いません。何でもやりたいことをできるのです。Django の構成要素 – モデル、ビュー、テンプレー ト – は、互いに切り離して利用できるのです。
これらはほんの一部にすぎません¶
以上、 Django の機能についてざっと紹介してきました。 Django は他にもまだま だ便利な機能を備えています:
- memcached などのバックエンドを組み込んだ キャッシュフレームワーク 。
- 小さな Python クラスを書くだけで簡単に RSS や Atom フィードを生成できる 配信フィードフレームワーク 。
- 自動生成される admin のセクシーな機能の数々。ここで紹介したのはほんの表層の一部でしかありません。
次は、あなたが Django をダウンロード して、 チュートリアル を読み、 コミュニティ に参加する番です。ご精読ありがとうございました!