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