Arthur de Jong

Open Source / Free Software developer

summaryrefslogtreecommitdiffstats
path: root/docs/intro/overview.txt
blob: 551310e900d9a131841b3602984bdf7ac506f70a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
==================
Django at a glance
==================

Because Django was developed in a fast-paced newsroom environment, it was
designed to make common Web-development tasks fast and easy. Here's an informal
overview of how to write a database-driven Web app with Django.

The goal of this document is to give you enough technical specifics to
understand how Django works, but this isn't intended to be a tutorial or
reference -- but we've got both! When you're ready to start a project, you can
:doc:`start with the tutorial </intro/tutorial01>` or :doc:`dive right into more
detailed documentation </topics/index>`.

Design your model
=================

Although you can use Django without a database, it comes with an
`object-relational mapper`_ in which you describe your database layout in Python
code.

.. _object-relational mapper: https://en.wikipedia.org/wiki/Object-relational_mapping

The :doc:`data-model syntax </topics/db/models>` offers many rich ways of
representing your models -- so far, it's been solving many years' worth of
database-schema problems. Here's a quick example:

.. snippet::
    :filename: mysite/news/models.py

    from django.db import models

    class Reporter(models.Model):
        full_name = models.CharField(max_length=70)

        def __str__(self):              # __unicode__ on Python 2
            return self.full_name

    class Article(models.Model):
        pub_date = models.DateField()
        headline = models.CharField(max_length=200)
        content = models.TextField()
        reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)

        def __str__(self):              # __unicode__ on Python 2
            return self.headline

Install it
==========

Next, run the Django command-line utility to create the database tables
automatically:

.. code-block:: console

    $ python manage.py migrate

The :djadmin:`migrate` command looks at all your available models and creates
tables in your database for whichever tables don't already exist, as well as
optionally providing :doc:`much richer schema control </topics/migrations>`.

Enjoy the free API
==================

With that, you've got a free, and rich, :doc:`Python API </topics/db/queries>`
to access your data. The API is created on the fly, no code generation
necessary:

.. code-block:: python

    # Import the models we created from our "news" app
    >>> from news.models import Reporter, Article

    # No reporters are in the system yet.
    >>> Reporter.objects.all()
    <QuerySet []>

    # Create a new Reporter.
    >>> r = Reporter(full_name='John Smith')

    # Save the object into the database. You have to call save() explicitly.
    >>> r.save()

    # Now it has an ID.
    >>> r.id
    1

    # Now the new reporter is in the database.
    >>> Reporter.objects.all()
    <QuerySet [<Reporter: John Smith>]>

    # Fields are represented as attributes on the Python object.
    >>> r.full_name
    'John Smith'

    # Django provides a rich database lookup API.
    >>> Reporter.objects.get(id=1)
    <Reporter: John Smith>
    >>> Reporter.objects.get(full_name__startswith='John')
    <Reporter: John Smith>
    >>> Reporter.objects.get(full_name__contains='mith')
    <Reporter: John Smith>
    >>> Reporter.objects.get(id=2)
    Traceback (most recent call last):
        ...
    DoesNotExist: Reporter matching query does not exist.

    # Create an article.
    >>> from datetime import date
    >>> a = Article(pub_date=date.today(), headline='Django is cool',
    ...     content='Yeah.', reporter=r)
    >>> a.save()

    # Now the article is in the database.
    >>> Article.objects.all()
    <QuerySet [<Article: Django is cool>]>

    # Article objects get API access to related Reporter objects.
    >>> r = a.reporter
    >>> r.full_name
    'John Smith'

    # And vice versa: Reporter objects get API access to Article objects.
    >>> r.article_set.all()
    <QuerySet [<Article: Django is cool>]>

    # The API follows relationships as far as you need, performing efficient
    # JOINs for you behind the scenes.
    # This finds all articles by a reporter whose name starts with "John".
    >>> Article.objects.filter(reporter__full_name__startswith='John')
    <QuerySet [<Article: Django is cool>]>

    # Change an object by altering its attributes and calling save().
    >>> r.full_name = 'Billy Goat'
    >>> r.save()

    # Delete an object with delete().
    >>> r.delete()

A dynamic admin interface: it's not just scaffolding -- it's the whole house
============================================================================

Once your models are defined, Django can automatically create a professional,
production ready :doc:`administrative interface </ref/contrib/admin/index>` --
a Web site that lets authenticated users add, change and delete objects. It's
as easy as registering your model in the admin site:

.. snippet::
    :filename: mysite/news/models.py

    from django.db import models

    class Article(models.Model):
        pub_date = models.DateField()
        headline = models.CharField(max_length=200)
        content = models.TextField()
        reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)

.. snippet::
    :filename: mysite/news/admin.py

    from django.contrib import admin

    from . import models

    admin.site.register(models.Article)

The philosophy here is that your site is edited by a staff, or a client, or
maybe just you -- and you don't want to have to deal with creating backend
interfaces just to manage content.

One typical workflow in creating Django apps is to create models and get the
admin sites up and running as fast as possible, so your staff (or clients) can
start populating data. Then, develop the way data is presented to the public.

Design your URLs
================

A clean, elegant URL scheme is an important detail in a high-quality Web
application. Django encourages beautiful URL design and doesn't put any cruft
in URLs, like ``.php`` or ``.asp``.

To design URLs for an app, you create a Python module called a :doc:`URLconf
</topics/http/urls>`. A table of contents for your app, it contains a simple
mapping between URL patterns and Python callback functions. URLconfs also serve
to decouple URLs from Python code.

Here's what a URLconf might look like for the ``Reporter``/``Article``
example above:

.. snippet::
    :filename: mysite/news/urls.py

    from django.conf.urls import url

    from . import views

    urlpatterns = [
        url(r'^articles/([0-9]{4})/$', views.year_archive),
        url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
        url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
    ]

The code above maps URLs, as simple `regular expressions`_, to the location of
Python callback functions ("views"). The regular expressions use parenthesis to
"capture" values from the URLs. When a user requests a page, Django runs
through each pattern, in order, and stops at the first one that matches the
requested URL. (If none of them matches, Django calls a special-case 404 view.)
This is blazingly fast, because the regular expressions are compiled at load
time.

.. _regular expressions: https://docs.python.org/howto/regex.html

Once one of the regexes matches, Django imports and calls the given view, which
is a simple Python function. Each view gets passed a request object --
which contains request metadata -- and the values captured in the regex.

For example, if a user requested the URL "/articles/2005/05/39323/", Django
would call the function ``news.views.article_detail(request,
'2005', '05', '39323')``.

Write your views
================

Each view is responsible for doing one of two things: Returning an
:class:`~django.http.HttpResponse` object containing the content for the
requested page, or raising an exception such as :class:`~django.http.Http404`.
The rest is up to you.

Generally, a view retrieves data according to the parameters, loads a template
and renders the template with the retrieved data. Here's an example view for
``year_archive`` from above:

.. snippet::
    :filename: mysite/news/views.py

    from django.shortcuts import render

    from .models import Article

    def year_archive(request, year):
        a_list = Article.objects.filter(pub_date__year=year)
        context = {'year': year, 'article_list': a_list}
        return render(request, 'news/year_archive.html', context)

This example uses Django's :doc:`template system </topics/templates>`, which has
several powerful features but strives to stay simple enough for non-programmers
to use.

Design your templates
=====================

The code above loads the ``news/year_archive.html`` template.

Django has a template search path, which allows you to minimize redundancy among
templates. In your Django settings, you specify a list of directories to check
for templates with :setting:`DIRS <TEMPLATES-DIRS>`. If a template doesn't exist
in the first directory, it checks the second, and so on.

Let's say the ``news/year_archive.html`` template was found. Here's what that
might look like:

.. snippet:: html+django
    :filename: mysite/news/templates/news/year_archive.html

    {% extends "base.html" %}

    {% block title %}Articles for {{ year }}{% endblock %}

    {% block content %}
    <h1>Articles for {{ year }}</h1>

    {% for article in article_list %}
        <p>{{ article.headline }}</p>
        <p>By {{ article.reporter.full_name }}</p>
        <p>Published {{ article.pub_date|date:"F j, Y" }}</p>
    {% endfor %}
    {% endblock %}

Variables are surrounded by double-curly braces. ``{{ article.headline }}``
means "Output the value of the article's headline attribute." But dots aren't
used only for attribute lookup. They also can do dictionary-key lookup, index
lookup and function calls.

Note ``{{ article.pub_date|date:"F j, Y" }}`` uses a Unix-style "pipe" (the "|"
character). This is called a template filter, and it's a way to filter the value
of a variable. In this case, the date filter formats a Python datetime object in
the given format (as found in PHP's date function).

You can chain together as many filters as you'd like. You can write :ref:`custom
template filters <howto-writing-custom-template-filters>`. You can write
:doc:`custom template tags </howto/custom-template-tags>`, which run custom
Python code behind the scenes.

Finally, Django uses the concept of "template inheritance". That's what the
``{% extends "base.html" %}`` does. It means "First load the template called
'base', which has defined a bunch of blocks, and fill the blocks with the
following blocks." In short, that lets you dramatically cut down on redundancy
in templates: each template has to define only what's unique to that template.

Here's what the "base.html" template, including the use of :doc:`static files
</howto/static-files/index>`, might look like:

.. snippet:: html+django
    :filename: mysite/templates/base.html

    {% load staticfiles %}
    <html>
    <head>
        <title>{% block title %}{% endblock %}</title>
    </head>
    <body>
        <img src="{% static "images/sitelogo.png" %}" alt="Logo" />
        {% block content %}{% endblock %}
    </body>
    </html>

Simplistically, it defines the look-and-feel of the site (with the site's logo),
and provides "holes" for child templates to fill. This makes a site redesign as
easy as changing a single file -- the base template.

It also lets you create multiple versions of a site, with different base
templates, while reusing child templates. Django's creators have used this
technique to create strikingly different mobile versions of sites -- simply by
creating a new base template.

Note that you don't have to use Django's template system if you prefer another
system. While Django's template system is particularly well-integrated with
Django's model layer, nothing forces you to use it. For that matter, you don't
have to use Django's database API, either. You can use another database
abstraction layer, you can read XML files, you can read files off disk, or
anything you want. Each piece of Django -- models, views, templates -- is
decoupled from the next.

This is just the surface
========================

This has been only a quick overview of Django's functionality. Some more useful
features:

* A :doc:`caching framework </topics/cache>` that integrates with memcached
  or other backends.

* A :doc:`syndication framework </ref/contrib/syndication>` that makes
  creating RSS and Atom feeds as easy as writing a small Python class.

* More sexy automatically-generated admin features -- this overview barely
  scratched the surface.

The next obvious steps are for you to `download Django`_, read :doc:`the
tutorial </intro/tutorial01>` and join `the community`_. Thanks for your
interest!

.. _download Django: https://www.djangoproject.com/download/
.. _the community: https://www.djangoproject.com/community/