| 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(max_length=70) |
|---|
| 29 |
|
|---|
| 30 |
def __unicode__(self): |
|---|
| 31 |
return self.full_name |
|---|
| 32 |
|
|---|
| 33 |
class Article(models.Model): |
|---|
| 34 |
pub_date = models.DateTimeField() |
|---|
| 35 |
headline = models.CharField(max_length=200) |
|---|
| 36 |
article = models.TextField() |
|---|
| 37 |
reporter = models.ForeignKey(Reporter) |
|---|
| 38 |
|
|---|
| 39 |
def __unicode__(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(max_length=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 |
.. _syndication framework: ../syndication_feeds/ |
|---|
| 297 |
|
|---|
| 298 |
The next obvious steps are for you to `download Django`_, read `the tutorial`_ |
|---|
| 299 |
and join `the community`_. Thanks for your interest! |
|---|
| 300 |
|
|---|
| 301 |
.. _download Django: http://www.djangoproject.com/download/ |
|---|
| 302 |
.. _the tutorial: ../tutorial01/ |
|---|
| 303 |
.. _the community: http://www.djangoproject.com/community/ |
|---|