|
1 ================== |
|
2 Django at a glance |
|
3 ================== |
|
4 |
|
5 Because Django was developed in a fast-paced newsroom environment, it was |
|
6 designed to make common Web-development tasks fast and easy. Here's an informal |
|
7 overview of how to write a database-driven Web app with Django. |
|
8 |
|
9 The goal of this document is to give you enough technical specifics to |
|
10 understand how Django works, but this isn't intended to be a tutorial or |
|
11 reference. Please see our more-detailed Django documentation_ when you're ready |
|
12 to start a project. |
|
13 |
|
14 .. _documentation: ../ |
|
15 |
|
16 Design your model |
|
17 ================= |
|
18 |
|
19 Although you can use Django without a database, it comes with an |
|
20 object-relational mapper in which you describe your database layout in Python |
|
21 code. |
|
22 |
|
23 The data-model syntax offers many rich ways of representing your models -- so |
|
24 far, it's been solving two years' worth of database-schema problems. Here's a |
|
25 quick example:: |
|
26 |
|
27 class Reporter(models.Model): |
|
28 full_name = models.CharField(maxlength=70) |
|
29 |
|
30 def __str__(self): |
|
31 return self.full_name |
|
32 |
|
33 class Article(models.Model): |
|
34 pub_date = models.DateTimeField() |
|
35 headline = models.CharField(maxlength=200) |
|
36 article = models.TextField() |
|
37 reporter = models.ForeignKey(Reporter) |
|
38 |
|
39 def __str__(self): |
|
40 return self.headline |
|
41 |
|
42 Install it |
|
43 ========== |
|
44 |
|
45 Next, run the Django command-line utility to create the database tables |
|
46 automatically:: |
|
47 |
|
48 manage.py syncdb |
|
49 |
|
50 The ``syncdb`` command looks at all your available models and creates tables |
|
51 in your database for whichever tables don't already exist. |
|
52 |
|
53 Enjoy the free API |
|
54 ================== |
|
55 |
|
56 With that, you've got a free, and rich, Python API to access your data. The API |
|
57 is created on the fly: No code generation necessary:: |
|
58 |
|
59 >>> from mysite.models import Reporter, Article |
|
60 |
|
61 # No reporters are in the system yet. |
|
62 >>> Reporter.objects.all() |
|
63 [] |
|
64 |
|
65 # Create a new Reporter. |
|
66 >>> r = Reporter(full_name='John Smith') |
|
67 |
|
68 # Save the object into the database. You have to call save() explicitly. |
|
69 >>> r.save() |
|
70 |
|
71 # Now it has an ID. |
|
72 >>> r.id |
|
73 1 |
|
74 |
|
75 # Now the new reporter is in the database. |
|
76 >>> Reporter.objects.all() |
|
77 [John Smith] |
|
78 |
|
79 # Fields are represented as attributes on the Python object. |
|
80 >>> r.full_name |
|
81 'John Smith' |
|
82 |
|
83 # Django provides a rich database lookup API. |
|
84 >>> Reporter.objects.get(id=1) |
|
85 John Smith |
|
86 >>> Reporter.objects.get(full_name__startswith='John') |
|
87 John Smith |
|
88 >>> Reporter.objects.get(full_name__contains='mith') |
|
89 John Smith |
|
90 >>> Reporter.objects.get(id=2) |
|
91 Traceback (most recent call last): |
|
92 ... |
|
93 DoesNotExist: Reporter does not exist for {'id__exact': 2} |
|
94 |
|
95 # Create an article. |
|
96 >>> from datetime import datetime |
|
97 >>> a = Article(pub_date=datetime.now(), headline='Django is cool', |
|
98 ... article='Yeah.', reporter=r) |
|
99 >>> a.save() |
|
100 |
|
101 # Now the article is in the database. |
|
102 >>> Article.objects.all() |
|
103 [Django is cool] |
|
104 |
|
105 # Article objects get API access to related Reporter objects. |
|
106 >>> r = a.reporter |
|
107 >>> r.full_name |
|
108 'John Smith' |
|
109 |
|
110 # And vice versa: Reporter objects get API access to Article objects. |
|
111 >>> r.article_set.all() |
|
112 [Django is cool] |
|
113 |
|
114 # The API follows relationships as far as you need, performing efficient |
|
115 # JOINs for you behind the scenes. |
|
116 # This finds all articles by a reporter whose name starts with "John". |
|
117 >>> Article.objects.filter(reporter__full_name__startswith="John") |
|
118 [Django is cool] |
|
119 |
|
120 # Change an object by altering its attributes and calling save(). |
|
121 >>> r.full_name = 'Billy Goat' |
|
122 >>> r.save() |
|
123 |
|
124 # Delete an object with delete(). |
|
125 >>> r.delete() |
|
126 |
|
127 A dynamic admin interface: It's not just scaffolding -- it's the whole house |
|
128 ============================================================================ |
|
129 |
|
130 Once your models are defined, Django can automatically create a professional, |
|
131 production ready administrative interface -- a Web site that lets authenticated |
|
132 users add, change and delete objects. It's as easy as adding a line of code to |
|
133 your model classes:: |
|
134 |
|
135 class Article(models.Model): |
|
136 pub_date = models.DateTimeField() |
|
137 headline = models.CharField(maxlength=200) |
|
138 article = models.TextField() |
|
139 reporter = models.ForeignKey(Reporter) |
|
140 class Admin: pass |
|
141 |
|
142 The philosophy here is that your site is edited by a staff, or a client, or |
|
143 maybe just you -- and you don't want to have to deal with creating backend |
|
144 interfaces just to manage content. |
|
145 |
|
146 One typical workflow in creating Django apps is to create models and get the |
|
147 admin sites up and running as fast as possible, so your staff (or clients) can |
|
148 start populating data. Then, develop the way data is presented to the public. |
|
149 |
|
150 Design your URLs |
|
151 ================ |
|
152 |
|
153 A clean, elegant URL scheme is an important detail in a high-quality Web |
|
154 application. Django encourages beautiful URL design and doesn't put any cruft |
|
155 in URLs, like ``.php`` or ``.asp``. |
|
156 |
|
157 To design URLs for an app, you create a Python module called a URLconf. A table |
|
158 of contents for your app, it contains a simple mapping between URL patterns and |
|
159 Python callback functions. URLconfs also serve to decouple URLs from Python |
|
160 code. |
|
161 |
|
162 Here's what a URLconf might look like for the ``Reporter``/``Article`` |
|
163 example above:: |
|
164 |
|
165 from django.conf.urls.defaults import * |
|
166 |
|
167 urlpatterns = patterns('', |
|
168 (r'^/articles/(\d{4})/$', 'mysite.views.year_archive'), |
|
169 (r'^/articles/(\d{4})/(\d{2})/$', 'mysite.views.month_archive'), |
|
170 (r'^/articles/(\d{4})/(\d{2})/(\d+)/$', 'mysite.views.article_detail'), |
|
171 ) |
|
172 |
|
173 The code above maps URLs, as simple regular expressions, to the location of |
|
174 Python callback functions ("views"). The regular expressions use parenthesis to |
|
175 "capture" values from the URLs. When a user requests a page, Django runs |
|
176 through each pattern, in order, and stops at the first one that matches the |
|
177 requested URL. (If none of them matches, Django calls a special-case 404 view.) |
|
178 This is blazingly fast, because the regular expressions are compiled at load |
|
179 time. |
|
180 |
|
181 Once one of the regexes matches, Django imports and calls the given view, which |
|
182 is a simple Python function. Each view gets passed a request object -- |
|
183 which contains request metadata -- and the values captured in the regex. |
|
184 |
|
185 For example, if a user requested the URL "/articles/2005/05/39323/", Django |
|
186 would call the function ``mysite.views.article_detail(request, |
|
187 '2005', '05', '39323')``. |
|
188 |
|
189 Write your views |
|
190 ================ |
|
191 |
|
192 Each view is responsible for doing one of two things: Returning an |
|
193 ``HttpResponse`` object containing the content for the requested page, or |
|
194 raising an exception such as ``Http404``. The rest is up to you. |
|
195 |
|
196 Generally, a view retrieves data according to the parameters, loads a template |
|
197 and renders the template with the retrieved data. Here's an example view for |
|
198 ``year_archive`` from above:: |
|
199 |
|
200 def year_archive(request, year): |
|
201 a_list = Article.objects.filter(pub_date__year=year) |
|
202 return render_to_response('news/year_archive.html', {'year': year, 'article_list': a_list}) |
|
203 |
|
204 This example uses Django's template system, which has several powerful |
|
205 features but strives to stay simple enough for non-programmers to use. |
|
206 |
|
207 Design your templates |
|
208 ===================== |
|
209 |
|
210 The code above loads the ``news/year_archive.html`` template. |
|
211 |
|
212 Django has a template search path, which allows you to minimize redundancy among |
|
213 templates. In your Django settings, you specify a list of directories to check |
|
214 for templates. If a template doesn't exist in the first directory, it checks the |
|
215 second, and so on. |
|
216 |
|
217 Let's say the ``news/article_detail.html`` template was found. Here's what that |
|
218 might look like:: |
|
219 |
|
220 {% extends "base.html" %} |
|
221 |
|
222 {% block title %}Articles for {{ year }}{% endblock %} |
|
223 |
|
224 {% block content %} |
|
225 <h1>Articles for {{ year }}</h1> |
|
226 |
|
227 {% for article in article_list %} |
|
228 <p>{{ article.headline }}</p> |
|
229 <p>By {{ article.reporter.full_name }}</p> |
|
230 <p>Published {{ article.pub_date|date:"F j, Y" }}</p> |
|
231 {% endfor %} |
|
232 {% endblock %} |
|
233 |
|
234 Variables are surrounded by double-curly braces. ``{{ article.headline }}`` |
|
235 means "Output the value of the article's headline attribute." But dots aren't |
|
236 used only for attribute lookup: They also can do dictionary-key lookup, index |
|
237 lookup and function calls. |
|
238 |
|
239 Note ``{{ article.pub_date|date:"F j, Y" }}`` uses a Unix-style "pipe" (the "|" |
|
240 character). This is called a template filter, and it's a way to filter the value |
|
241 of a variable. In this case, the date filter formats a Python datetime object in |
|
242 the given format (as found in PHP's date function; yes, there is one good idea |
|
243 in PHP). |
|
244 |
|
245 You can chain together as many filters as you'd like. You can write custom |
|
246 filters. You can write custom template tags, which run custom Python code behind |
|
247 the scenes. |
|
248 |
|
249 Finally, Django uses the concept of "template inheritance": That's what the |
|
250 ``{% extends "base.html" %}`` does. It means "First load the template called |
|
251 'base', which has defined a bunch of blocks, and fill the blocks with the |
|
252 following blocks." In short, that lets you dramatically cut down on redundancy |
|
253 in templates: Each template has to define only what's unique to that template. |
|
254 |
|
255 Here's what the "base.html" template might look like:: |
|
256 |
|
257 <html> |
|
258 <head> |
|
259 <title>{% block title %}{% endblock %}</title> |
|
260 </head> |
|
261 <body> |
|
262 <img src="sitelogo.gif" alt="Logo" /> |
|
263 {% block content %}{% endblock %} |
|
264 </body> |
|
265 </html> |
|
266 |
|
267 Simplistically, it defines the look-and-feel of the site (with the site's logo), |
|
268 and provides "holes" for child templates to fill. This makes a site redesign as |
|
269 easy as changing a single file -- the base template. |
|
270 |
|
271 It also lets you create multiple versions of a site, with different base |
|
272 templates, while reusing child templates. Django's creators have used this |
|
273 technique to create strikingly different cell-phone editions of sites -- simply |
|
274 by creating a new base template. |
|
275 |
|
276 Note that you don't have to use Django's template system if you prefer another |
|
277 system. While Django's template system is particularly well-integrated with |
|
278 Django's model layer, nothing forces you to use it. For that matter, you don't |
|
279 have to use Django's database API, either. You can use another database |
|
280 abstraction layer, you can read XML files, you can read files off disk, or |
|
281 anything you want. Each piece of Django -- models, views, templates -- is |
|
282 decoupled from the next. |
|
283 |
|
284 This is just the surface |
|
285 ======================== |
|
286 |
|
287 This has been only a quick overview of Django's functionality. Some more useful |
|
288 features: |
|
289 |
|
290 * A caching framework that integrates with memcached or other backends. |
|
291 * A syndication framework that makes creating RSS and Atom feeds as easy as |
|
292 writing a small Python class. |
|
293 * More sexy automatically-generated admin features -- this overview barely |
|
294 scratched the surface. |
|
295 |
|
296 The next obvious steps are for you to `download Django`_, read `the tutorial`_ |
|
297 and join `the community`_. Thanks for your interest! |
|
298 |
|
299 .. _download Django: http://www.djangoproject.com/download/ |
|
300 .. _the tutorial: http://www.djangoproject.com/documentation/tutorial1/ |
|
301 .. _the community: http://www.djangoproject.com/community/ |