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