| 1 |
=================== |
|---|
| 2 |
Design philosophies |
|---|
| 3 |
=================== |
|---|
| 4 |
|
|---|
| 5 |
This document explains some of the fundamental philosophies Django's developers |
|---|
| 6 |
have used in creating the framework. Its goal is to explain the past and guide |
|---|
| 7 |
the future. |
|---|
| 8 |
|
|---|
| 9 |
Overall |
|---|
| 10 |
======= |
|---|
| 11 |
|
|---|
| 12 |
Loose coupling |
|---|
| 13 |
-------------- |
|---|
| 14 |
|
|---|
| 15 |
A fundamental goal of Django's stack is `loose coupling and tight cohesion`_. |
|---|
| 16 |
The various layers of the framework shouldn't "know" about each other unless |
|---|
| 17 |
absolutely necessary. |
|---|
| 18 |
|
|---|
| 19 |
For example, the template system knows nothing about Web requests, the database |
|---|
| 20 |
layer knows nothing about data display and the view system doesn't care which |
|---|
| 21 |
template system a programmer uses. |
|---|
| 22 |
|
|---|
| 23 |
.. _`loose coupling and tight cohesion`: http://c2.com/cgi/wiki?CouplingAndCohesion |
|---|
| 24 |
|
|---|
| 25 |
Less code |
|---|
| 26 |
--------- |
|---|
| 27 |
|
|---|
| 28 |
Django apps should use as little code as possible; they should lack boilerplate. |
|---|
| 29 |
Django should take full advantage of Python's dynamic capabilities, such as |
|---|
| 30 |
introspection. |
|---|
| 31 |
|
|---|
| 32 |
Quick development |
|---|
| 33 |
----------------- |
|---|
| 34 |
|
|---|
| 35 |
The point of a Web framework in the 21st century is to make the tedious aspects |
|---|
| 36 |
of Web development fast. Django should allow for incredibly quick Web |
|---|
| 37 |
development. |
|---|
| 38 |
|
|---|
| 39 |
Don't repeat yourself (DRY) |
|---|
| 40 |
--------------------------- |
|---|
| 41 |
|
|---|
| 42 |
Every distinct concept and/or piece of data should live in one, and only one, |
|---|
| 43 |
place. Redundancy is bad. Normalization is good. |
|---|
| 44 |
|
|---|
| 45 |
The framework, within reason, should deduce as much as possible from as little |
|---|
| 46 |
as possible. |
|---|
| 47 |
|
|---|
| 48 |
Explicit is better than implicit |
|---|
| 49 |
-------------------------------- |
|---|
| 50 |
|
|---|
| 51 |
This, a `core Python principle`_, means Django shouldn't do too much "magic." |
|---|
| 52 |
Magic shouldn't happen unless there's a really good reason for it. |
|---|
| 53 |
|
|---|
| 54 |
.. _`core Python principle`: http://www.python.org/doc/Humor.html#zen |
|---|
| 55 |
|
|---|
| 56 |
Consistency |
|---|
| 57 |
----------- |
|---|
| 58 |
|
|---|
| 59 |
The framework should be consistent at all levels. Consistency applies to |
|---|
| 60 |
everything from low-level (the Python coding style used) to high-level (the |
|---|
| 61 |
"experience" of using Django). |
|---|
| 62 |
|
|---|
| 63 |
Models |
|---|
| 64 |
====== |
|---|
| 65 |
|
|---|
| 66 |
Explicit is better than implicit |
|---|
| 67 |
-------------------------------- |
|---|
| 68 |
|
|---|
| 69 |
Fields shouldn't assume certain behaviors based solely on the name of the |
|---|
| 70 |
field. This requires too much knowledge of the system and is prone to errors. |
|---|
| 71 |
Instead, behaviors should be based on keyword arguments and, in some cases, on |
|---|
| 72 |
the type of the field. |
|---|
| 73 |
|
|---|
| 74 |
Include all relevant domain logic |
|---|
| 75 |
--------------------------------- |
|---|
| 76 |
|
|---|
| 77 |
Models should encapsulate every aspect of an "object," following Martin |
|---|
| 78 |
Fowler's `Active Record`_ design pattern. |
|---|
| 79 |
|
|---|
| 80 |
This is why model-specific admin options are included in the model itself; data |
|---|
| 81 |
related to a model should be stored *in* the model. |
|---|
| 82 |
|
|---|
| 83 |
.. _`Active Record`: http://www.martinfowler.com/eaaCatalog/activeRecord.html |
|---|
| 84 |
|
|---|
| 85 |
Database API |
|---|
| 86 |
============ |
|---|
| 87 |
|
|---|
| 88 |
The core goals of the database API are: |
|---|
| 89 |
|
|---|
| 90 |
SQL efficiency |
|---|
| 91 |
-------------- |
|---|
| 92 |
|
|---|
| 93 |
It should execute SQL statements as few times as possible, and it should |
|---|
| 94 |
optimize statements internally. |
|---|
| 95 |
|
|---|
| 96 |
This is why developers need to call ``save()`` explicitly, rather than the |
|---|
| 97 |
framework saving things behind the scenes silently. |
|---|
| 98 |
|
|---|
| 99 |
This is also why the ``select_related`` argument exists. It's an optional |
|---|
| 100 |
performance booster for the common case of selecting "every related object." |
|---|
| 101 |
|
|---|
| 102 |
Terse, powerful syntax |
|---|
| 103 |
---------------------- |
|---|
| 104 |
|
|---|
| 105 |
The database API should allow rich, expressive statements in as little syntax |
|---|
| 106 |
as possible. It should not rely on importing other modules or helper objects. |
|---|
| 107 |
|
|---|
| 108 |
Joins should be performed automatically, behind the scenes, when necessary. |
|---|
| 109 |
|
|---|
| 110 |
Every object should be able to access every related object, systemwide. This |
|---|
| 111 |
access should work both ways. |
|---|
| 112 |
|
|---|
| 113 |
Option to drop into raw SQL easily, when needed |
|---|
| 114 |
----------------------------------------------- |
|---|
| 115 |
|
|---|
| 116 |
The database API should realize it's a shortcut but not necessarily an |
|---|
| 117 |
end-all-be-all. The framework should make it easy to write custom SQL -- entire |
|---|
| 118 |
statements, or just custom ``WHERE`` clauses as custom parameters to API calls. |
|---|
| 119 |
|
|---|
| 120 |
URL design |
|---|
| 121 |
========== |
|---|
| 122 |
|
|---|
| 123 |
Loose coupling |
|---|
| 124 |
-------------- |
|---|
| 125 |
|
|---|
| 126 |
URLs in a Django app should not be coupled to the underlying Python code. Tying |
|---|
| 127 |
URLs to Python function names is a Bad And Ugly Thing. |
|---|
| 128 |
|
|---|
| 129 |
Along these lines, the Django URL system should allow URLs for the same app to |
|---|
| 130 |
be different in different contexts. For example, one site may put stories at |
|---|
| 131 |
``/stories/``, while another may use ``/news/``. |
|---|
| 132 |
|
|---|
| 133 |
Infinite flexibility |
|---|
| 134 |
-------------------- |
|---|
| 135 |
|
|---|
| 136 |
URLs should be as flexible as possible. Any conceivable URL design should be |
|---|
| 137 |
allowed. |
|---|
| 138 |
|
|---|
| 139 |
Encourage best practices |
|---|
| 140 |
------------------------ |
|---|
| 141 |
|
|---|
| 142 |
The framework should make it just as easy (or even easier) for a developer to |
|---|
| 143 |
design pretty URLs than ugly ones. |
|---|
| 144 |
|
|---|
| 145 |
File extensions in Web-page URLs should be avoided. |
|---|
| 146 |
|
|---|
| 147 |
Definitive URLs |
|---|
| 148 |
--------------- |
|---|
| 149 |
|
|---|
| 150 |
Technically, ``foo.com/bar`` and ``foo.com/bar/`` are two different URLs, and |
|---|
| 151 |
search-engine robots (and some Web traffic-analyzing tools) would treat them as |
|---|
| 152 |
separate pages. Django should make an effort to "normalize" URLs so that |
|---|
| 153 |
search-engine robots don't get confused. |
|---|
| 154 |
|
|---|
| 155 |
This is the reasoning behind the ``APPEND_SLASH`` setting. |
|---|
| 156 |
|
|---|
| 157 |
Template system |
|---|
| 158 |
=============== |
|---|
| 159 |
|
|---|
| 160 |
Separate logic from presentation |
|---|
| 161 |
-------------------------------- |
|---|
| 162 |
|
|---|
| 163 |
We see a template system as a tool that controls presentation and |
|---|
| 164 |
presentation-related logic -- and that's it. The template system shouldn't |
|---|
| 165 |
support functionality that goes beyond this basic goal. |
|---|
| 166 |
|
|---|
| 167 |
If we wanted to put everything in templates, we'd be using PHP. Been there, |
|---|
| 168 |
done that, wised up. |
|---|
| 169 |
|
|---|
| 170 |
Discourage redundancy |
|---|
| 171 |
--------------------- |
|---|
| 172 |
|
|---|
| 173 |
The majority of dynamic Web sites use some sort of common sitewide design -- |
|---|
| 174 |
a common header, footer, navigation bar, etc. The Django template system should |
|---|
| 175 |
make it easy to store those elements in a single place, eliminating duplicate |
|---|
| 176 |
code. |
|---|
| 177 |
|
|---|
| 178 |
This is the philosophy behind `template inheritance`_. |
|---|
| 179 |
|
|---|
| 180 |
.. _template inheritance: http://www.djangoproject.com/documentation/templates/#template-inheritance |
|---|
| 181 |
|
|---|
| 182 |
Be decoupled from HTML |
|---|
| 183 |
---------------------- |
|---|
| 184 |
|
|---|
| 185 |
The template system shouldn't be designed so that it only outputs HTML. It |
|---|
| 186 |
should be equally good at generating other text-based formats, or just plain |
|---|
| 187 |
text. |
|---|
| 188 |
|
|---|
| 189 |
Assume designer competence |
|---|
| 190 |
-------------------------- |
|---|
| 191 |
|
|---|
| 192 |
The template system shouldn't be designed so that templates necessarily are |
|---|
| 193 |
displayed nicely in WYSIWYG editors such as Dreamweaver. That is too severe of |
|---|
| 194 |
a limitation and wouldn't allow the syntax to be as nice as it is. Django |
|---|
| 195 |
expects template authors are comfortable editing HTML directly. |
|---|
| 196 |
|
|---|
| 197 |
Treat whitespace obviously |
|---|
| 198 |
-------------------------- |
|---|
| 199 |
|
|---|
| 200 |
The template system shouldn't do magic things with whitespace. If a template |
|---|
| 201 |
includes whitespace, the system should treat the whitespace as it treats text |
|---|
| 202 |
-- just display it. Any whitespace that's not in a template tag should be |
|---|
| 203 |
displayed. |
|---|
| 204 |
|
|---|
| 205 |
Don't invent a programming language |
|---|
| 206 |
----------------------------------- |
|---|
| 207 |
|
|---|
| 208 |
The template system intentionally doesn't allow the following: |
|---|
| 209 |
|
|---|
| 210 |
* Assignment to variables |
|---|
| 211 |
* Advanced logic |
|---|
| 212 |
|
|---|
| 213 |
The goal is not to invent a programming language. The goal is to offer just |
|---|
| 214 |
enough programming-esque functionality, such as branching and looping, that is |
|---|
| 215 |
essential for making presentation-related decisions. |
|---|
| 216 |
|
|---|
| 217 |
The Django template system recognizes that templates are most often written by |
|---|
| 218 |
*designers*, not *programmers*, and therefore should not assume Python |
|---|
| 219 |
knowledge. |
|---|
| 220 |
|
|---|
| 221 |
Safety and security |
|---|
| 222 |
------------------- |
|---|
| 223 |
|
|---|
| 224 |
The template system, out of the box, should forbid the inclusion of malicious |
|---|
| 225 |
code -- such as commands that delete database records. |
|---|
| 226 |
|
|---|
| 227 |
This is another reason the template system doesn't allow arbitrary Python code. |
|---|
| 228 |
|
|---|
| 229 |
Extensibility |
|---|
| 230 |
------------- |
|---|
| 231 |
|
|---|
| 232 |
The template system should recognize that advanced template authors may want |
|---|
| 233 |
to extend its technology. |
|---|
| 234 |
|
|---|
| 235 |
This is the philosophy behind custom template tags and filters. |
|---|
| 236 |
|
|---|
| 237 |
Views |
|---|
| 238 |
===== |
|---|
| 239 |
|
|---|
| 240 |
Simplicity |
|---|
| 241 |
---------- |
|---|
| 242 |
|
|---|
| 243 |
Writing a view should be as simple as writing a Python function. Developers |
|---|
| 244 |
shouldn't have to instantiate a class when a function will do. |
|---|
| 245 |
|
|---|
| 246 |
Use request objects |
|---|
| 247 |
------------------- |
|---|
| 248 |
|
|---|
| 249 |
Views should have access to a request object -- an object that stores metadata |
|---|
| 250 |
about the current request. The object should be passed directly to a view |
|---|
| 251 |
function, rather than the view function having to access the request data from |
|---|
| 252 |
a global variable. This makes it light, clean and easy to test views by passing |
|---|
| 253 |
in "fake" request objects. |
|---|
| 254 |
|
|---|
| 255 |
Loose coupling |
|---|
| 256 |
-------------- |
|---|
| 257 |
|
|---|
| 258 |
A view shouldn't care about which template system the developer uses -- or even |
|---|
| 259 |
whether a template system is used at all. |
|---|
| 260 |
|
|---|
| 261 |
Designate between GET and POST |
|---|
| 262 |
------------------------------ |
|---|
| 263 |
|
|---|
| 264 |
GET and POST are distinct; developers should explicitly use one or the other. |
|---|
| 265 |
The framework should make it easy to distinguish between GET and POST data. |
|---|