このドキュメントでは、 Django の開発者たちがフレームワークの構築に取り入れ ている根本的な設計思想についていくつか解説します。それによって、 Django の これまでの経緯に説明を与えつつ、将来への指針にしたいと思います。
Django スタックの基本的な目標は、疎結合と高い凝集度 を実現することです。フレームワークの各レイヤーは絶対に必要でない限り、相手をお互いに「知る」べきではありません。
For example, the template system knows nothing about web requests, the database layer knows nothing about data display and the view system doesn't care which template system a programmer uses.
Django は利便性のためにフルスタックとなってはいますが、スタックのどのコンポーネントも、可能な限り独立させてあります。
Django のアプリはボイラープレートを書かなくて済むようにできるだけ短いコードになるようにされています。Django は、たとえばイントロスペクションなどの Python の動的な性質を最大限に生かすようになっています。
The point of a web framework in the 21st century is to make the tedious aspects of web development fast. Django should allow for incredibly quick web development.
多大に区別される概念やデータ構造は、ただ1箇所のみに存在するべきです。冗長性は悪であり、正規化は善です。
フレームワークは、合理的な範囲内で可能な限り少ないものからできる限り多くのものを推測するべきです。
これは、PEP 20 にリストアップされた Python の核となる原則の1つです。つまり、Django は「魔法」を使いすぎてはならないということです。魔法を使っても良いのは、それを本当に使うべき理由があるとき、他の方法では到達できない非常に大きな利便性があるときだけです。ある機能の使い方を学ぶ開発者を混乱させるような方法で実装してはいけません。
フレームワークはあらゆるレベルで一貫性を持たなければなりません。一貫性は、低レベル (採用する Python のコーディングスタイル) から高レベル (Django の使い方) までのあらゆる点で保たれなければなりません。
フィールド名のみに基づいてフィールドの振る舞いが決まるべきではありません。そのようにしてしまうと、システム全体に対する深い知識が必要となり、誤りの原因となりやすいです。その代わりに、キーワード引数や、場合によってはフィールドの型によって振る舞いが変わるようにします。
モジュールは、マーティン・ファウラーの Active Record のデザインパターンに従い、「オブジェクト」のすべての側面をカプセル化する必要がります。
その理由は、モジュール (人間に読みやすい名前や、デフォルトの順序のオプションなど) について、モデルと情報の両方が表現するデータはモデルクラスで定義されており、与えられたモデルを理解するのに必要なすべての情報はモデルの 中に 存在するべきだからです。
データベース API の主要な目的は、次のとおりです。
SQLステートメントはなるべく少ない回数実行されるべきで、またステートメントは内部で最適化されるべきです。
フレームワークが舞台裏で黙って保存するのではなく、開発者が明示的に save()
を呼び出す必要があるのはこのためです。
これは select_related()
QuerySet
メソッドが存在していることの理由でもあります。このメソッドは、「関係する全てのオブジェクト」を選択というよくあるケースでの効率上昇オプションです。
データベース API はできる限り小さい構文で、豊かで表現力のあるステートメントを書けるべきです。そして、それは他のモジュールや補助オブジェクトのインポートに頼るべきではありません。
結合処理は、必要なときに、舞台裏で自動的に行われるべきです。
全てのオブジェクトはシステム全域の全ての関係するオブジェクトにアクセスできるべきです。このアクセスは両方向にできるべきです。
The database API should realize it's a shortcut but not necessarily an
end-all-be-all. The framework should make it easy to write custom SQL -- entire
statements, or just custom WHERE
clauses as custom parameters to API calls.
URLs in a Django app should not be coupled to the underlying Python code. Tying URLs to Python function names is a Bad And Ugly Thing.
Along these lines, the Django URL system should allow URLs for the same app to
be different in different contexts. For example, one site may put stories at
/stories/
, while another may use /news/
.
URLは可能な限り柔軟性を持たせています。考えうる URL デザインが利用できます。
The framework should make it just as easy (or even easier) for a developer to design pretty URLs than ugly ones.
File extensions in web-page URLs should be avoided.
Vignette-style commas in URLs deserve severe punishment.
Technically, foo.com/bar
and foo.com/bar/
are two different URLs, and
search-engine robots (and some web traffic-analyzing tools) would treat them as
separate pages. Django should make an effort to "normalize" URLs so that
search-engine robots don't get confused.
This is the reasoning behind the APPEND_SLASH
setting.
私達は、テンプレートシステムはプレゼンテーションとプレゼンテーション関係のロジックを制御するためのツールであり、それ以上のものではないと考えています。 その本分をこえた機能をテンプレートシステムに求めるべきではありません。
大多数の動的な Web サイトでは、ヘッダやフッタ、ナビゲーションバーといった部分のデザインをサイト全体で共通にしています。 Django テンプレートシステムは、 こうしたサイトの構成要素を一箇所に保存しやすくし、重複したコードを削除する必要があります。
これが テンプレートの継承 の背後にある思想です。
テンプレートシステムは、ただ単に HTML だけを出力するように設計されてはいません。他のテキストベースのフォーマットや、単純なプレインテキストも同じように上手く生成できるように作られています。
テンプレートをパースするのに XML エンジンを使ってしまうと、テンプレートの編集に全く新しいヒューマンエラーの世界を作り出してしまい、結果として、テンプレート処理に受け入れられないようなレベルの困難を生み出してしまうでしょう。
必ずしも Dreamweaver のような WYSIWYG エディタでうまく表示できるように テンプレートシステムを設計する必要はありません。そのような要求は制限が厳しすぎ、本来あるべきすっきりした構文を実現できなくなります。 Django では 直接 HTML を編集する作業に慣れたテンプレート作者を想定しています。
テンプレートシステムは、ホワイトスペースに対して変わった処理を行うべきではありません。もしテンプレートにホワイトスペースが書かれていれば、他の文字と同じように扱って、それをそのまま表示するべきです。テンプレートタグの外に書かれたすべてのホワイトスペースは、そのまま表示するべきです。
私たちの目的は、新しいプログラミング言語を開発することではありません。本当の目的は、プログラミング言語が持つような機能を必要十分なだけ使えるようにすることです。たとえば、条件分岐やループといったもので、これらはプレゼンテーションに関連する決定を下すときに大切になります。 Django テンプレート言語 (Django Template Language; DTL) は、複雑なロジックを使わずにこの目的を達成するために作られました。
Django のテンプレートシステムは、テンプレートの書き手は プログラマー ではなく、主に デザイナー であることを念頭に置いています。そのため、Python の知識がまったくなくても書けるようになっています。
テンプレートシステムは、コマンドの実行やデータベースレコードの削除を行うような、悪意のあるコードの挿入ができないようになっていなければなりません。
これが、テンプレートシステムが任意の Python コードの実行を許さないようにできているもう一つの理由です。
ビューは、Python の関数を書くのと同じくらい簡単に書けるべきです。開発者は、ふつうに関数を書くときと同じように、クラスからインスタンスを作ったりせずにビューが書けるべきです。
ビューはリクエストオブジェクトにアクセスします。リクエストオブジェクトとは、 現在のリクエストに関するメタデータを入れるオブジェクトです。ビューはこのオブジェクトをグローバル変数経由でアクセスするのではなく、引数として直接受け取るようにすべきです。それにより、「偽の」リクエストオブジェクトを渡してビューを簡単かつクリーンにテストできるようになります。
ビューは、開発者がどのテンプレートシステムを使用しているか意識せずに使えるべきです。もっと言えば、テンプレートシステム自体を使っているかどうかも気にせずに使えるようにするべきです。
GET と POST は区別します。開発者は明示的に一方を他方と区別して明示的に使用するべきです。フレームワークは、GET と POST データを分かりやすく区別できるようにしなければなりません。
Django の キャッシュフレームワーク の主な目的は次の点にあります。
キャッシュは可能な限り高速でなければならない。したがって、キャッシュバックエンドを包んでいるフレームワークのコード (特に get()
操作) はすべて、極限まで短くするべきである。
キャッシュ API は、バックエントが違っていても一貫したインターフェイスを提供するべきである。
キャッシュ API は、開発者のニーズにもとづいて、アプリケーションレベルで拡張可能であるべきである (例としては Cache key transformation がある)。
2022年6月01日