~kkubasik/django/aggregation-branch

« back to all changes in this revision

Viewing changes to docs/tutorial02.txt

  • Committer: adrian
  • Date: 2006-05-02 01:31:56 UTC
  • Revision ID: vcs-imports@canonical.com-20060502013156-2941fcd40d080649
MERGED MAGIC-REMOVAL BRANCH TO TRUNK. This change is highly backwards-incompatible. Please read http://code.djangoproject.com/wiki/RemovingTheMagic for upgrade instructions.

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
Writing your first Django app, part 2
3
3
=====================================
4
4
 
5
 
By Adrian Holovaty <holovaty@gmail.com>
6
 
 
7
5
This tutorial begins where `Tutorial 1`_ left off. We're continuing the Web-poll
8
6
application and will focus on Django's automatically-generated admin site.
9
7
 
31
29
activate the admin site for your installation, do these three things:
32
30
 
33
31
    * Add ``"django.contrib.admin"`` to your ``INSTALLED_APPS`` setting.
34
 
    * Run the command ``python manage.py install admin``. This will create an
35
 
      extra database table that the admin needs.
36
 
    * Edit your ``myproject/urls.py`` file and uncomment the line below
 
32
    * Run ``python manage.py syncdb``. Since you have added a new application
 
33
      to ``INSTALLED_APPS``, the database tables need to be updated.
 
34
    * Edit your ``mysite/urls.py`` file and uncomment the line below
37
35
      "Uncomment this for admin:". This file is a URLconf; we'll dig into
38
36
      URLconfs in the next tutorial. For now, all you need to know is that it
39
37
      maps URL roots to applications.
40
38
 
41
 
Create a user account
42
 
=====================
43
 
 
44
 
Run the following command to create a superuser account for your admin site::
45
 
 
46
 
    python manage.py createsuperuser
47
 
 
48
 
The script will prompt you for a username, e-mail address and password (twice).
49
 
 
50
39
Start the development server
51
40
============================
52
41
 
82
71
But where's our poll app? It's not displayed on the admin index page.
83
72
 
84
73
Just one thing to do: We need to specify in the ``Poll`` model that ``Poll``
85
 
objects have an admin interface. Edit the ``myproject/polls/models/polls.py``
86
 
file and make the following change to add an inner ``META`` class with an
87
 
``admin`` attribute::
 
74
objects have an admin interface. Edit the ``mysite/polls/models/polls.py``
 
75
file and make the following change to add an inner ``Admin`` class::
88
76
 
89
 
    class Poll(meta.Model):
 
77
    class Poll(models.Model):
90
78
        # ...
91
 
        class META:
92
 
            admin = meta.Admin()
 
79
        class Admin:
 
80
            pass
93
81
 
94
 
The ``class META`` contains all `non-field metadata`_ about this model.
 
82
The ``class Admin`` will contain all the settings that control how this model
 
83
appears in the Django admin.  All the settings are optional, however, so
 
84
creating an empty class means "give this object an admin interface using
 
85
all the default options."
95
86
 
96
87
Now reload the Django admin page to see your changes. Note that you don't have
97
 
to restart the development server -- it auto-reloads code.
98
 
 
99
 
.. _non-field metadata: http://www.djangoproject.com/documentation/model_api/#meta-options
 
88
to restart the development server -- the server will auto-reloads your project,
 
89
so any modifications code will be seen immediately in your browser.
100
90
 
101
91
Explore the free admin functionality
102
92
====================================
103
93
 
104
 
Now that ``Poll`` has the ``admin`` attribute, Django knows that it should be
 
94
Now that ``Poll`` has the inner ``Admin`` class, Django knows that it should be
105
95
displayed on the admin index page:
106
96
 
107
97
.. image:: http://media.djangoproject.com/img/doc/tutorial/admin03t.png
125
115
Things to note here:
126
116
 
127
117
* The form is automatically generated from the Poll model.
128
 
* The different model field types (``meta.DateTimeField``, ``meta.CharField``)
 
118
* The different model field types (``models.DateTimeField``, ``models.CharField``)
129
119
  correspond to the appropriate HTML input widget. Each type of field knows
130
120
  how to display itself in the Django admin.
131
121
* Each ``DateTimeField`` gets free JavaScript shortcuts. Dates get a "Today"
157
147
Take a few minutes to marvel at all the code you didn't have to write.
158
148
 
159
149
Let's customize this a bit. We can reorder the fields by explicitly adding a
160
 
``fields`` parameter to ``meta.Admin``::
 
150
``fields`` parameter to ``Admin``::
161
151
 
162
 
        admin = meta.Admin(
 
152
        class Admin:
163
153
            fields = (
164
154
                (None, {'fields': ('pub_date', 'question')}),
165
 
            ),
166
 
        )
 
155
            )
167
156
 
168
157
That made the "Publication date" show up first instead of second:
169
158
 
176
165
And speaking of forms with dozens of fields, you might want to split the form
177
166
up into fieldsets::
178
167
 
179
 
        admin = meta.Admin(
 
168
        class Admin:
180
169
            fields = (
181
170
                (None, {'fields': ('question',)}),
182
171
                ('Date information', {'fields': ('pub_date',)}),
183
 
            ),
184
 
        )
 
172
            )
185
173
 
186
174
The first element of each tuple in ``fields`` is the title of the fieldset.
187
175
Here's what our form looks like now:
195
183
This is useful when you have a long form that contains a number of fields that
196
184
aren't commonly used::
197
185
 
198
 
        admin = meta.Admin(
 
186
        class Admin:
199
187
            fields = (
200
188
                (None, {'fields': ('question',)}),
201
189
                ('Date information', {'fields': ('pub_date',), 'classes': 'collapse'}),
202
 
            ),
203
 
        )
 
190
            )
204
191
 
205
192
.. image:: http://media.djangoproject.com/img/doc/tutorial/admin09.png
206
193
   :alt: Fieldset is initially collapsed
214
201
Yet.
215
202
 
216
203
There are two ways to solve this problem. The first is to give the ``Choice``
217
 
model its own ``admin`` attribute, just as we did with ``Poll``. Here's what
 
204
model its own inner ``Admin`` class, just as we did with ``Poll``. Here's what
218
205
that would look like::
219
206
 
220
 
    class Choice(meta.Model):
 
207
    class Choice(models.Model):
221
208
        # ...
222
 
        class META:
223
 
            admin = meta.Admin()
 
209
        class Admin:
 
210
            pass
224
211
 
225
212
Now "Choices" is an available option in the Django admin. The "Add choice" form
226
213
looks like this:
242
229
It'd be better if you could add a bunch of Choices directly when you create the
243
230
Poll object. Let's make that happen.
244
231
 
245
 
Remove the ``admin`` for the Choice model. Then, edit the ``ForeignKey(Poll)``
 
232
Remove the ``Admin`` for the Choice model. Then, edit the ``ForeignKey(Poll)``
246
233
field like so::
247
234
 
248
 
    poll = meta.ForeignKey(Poll, edit_inline=meta.STACKED, num_in_admin=3)
 
235
    poll = models.ForeignKey(Poll, edit_inline=models.STACKED, num_in_admin=3)
249
236
 
250
237
This tells Django: "Choice objects are edited on the Poll admin page. By
251
238
default, provide enough fields for 3 Choices."
252
239
 
253
240
Then change the other fields in ``Choice`` to give them ``core=True``::
254
241
 
255
 
    choice = meta.CharField(maxlength=200, core=True)
256
 
    votes = meta.IntegerField(core=True)
 
242
    choice = models.CharField(maxlength=200, core=True)
 
243
    votes = models.IntegerField(core=True)
257
244
 
258
245
This tells Django: "When you edit a Choice on the Poll admin page, the 'choice'
259
246
and 'votes' fields are required. The presence of at least one of them signifies
277
264
fields for entering related Choice objects. For that reason, Django offers an
278
265
alternate way of displaying inline related objects::
279
266
 
280
 
    poll = meta.ForeignKey(Poll, edit_inline=meta.TABULAR, num_in_admin=3)
 
267
    poll = models.ForeignKey(Poll, edit_inline=models.TABULAR, num_in_admin=3)
281
268
 
282
 
With that ``edit_inline=meta.TABULAR`` (instead of ``meta.STACKED``), the
 
269
With that ``edit_inline=models.TABULAR`` (instead of ``models.STACKED``), the
283
270
related objects are displayed in a more compact, table-based format:
284
271
 
285
272
.. image:: http://media.djangoproject.com/img/doc/tutorial/admin12.png
302
289
``list_display`` option, which is a tuple of field names to display, as columns,
303
290
on the change list page for the object::
304
291
 
305
 
    class Poll(meta.Model):
 
292
    class Poll(models.Model):
306
293
        # ...
307
 
        class META:
308
 
            admin = meta.Admin(
309
 
                # ...
310
 
                list_display = ('question', 'pub_date'),
311
 
            )
 
294
        class Admin:
 
295
            # ...
 
296
            list_display = ('question', 'pub_date')
312
297
 
313
298
Just for good measure, let's also include the ``was_published_today`` custom
314
299
method from Tutorial 1::
315
300
 
316
 
    list_display = ('question', 'pub_date', 'was_published_today'),
 
301
    list_display = ('question', 'pub_date', 'was_published_today')
317
302
 
318
303
Now the poll change list page looks like this:
319
304
 
336
321
Let's add another improvement to the Poll change list page: Filters. Add the
337
322
following line to ``Poll.admin``::
338
323
 
339
 
    list_filter = ['pub_date'],
 
324
    list_filter = ['pub_date']
340
325
 
341
326
That adds a "Filter" sidebar that lets people filter the change list by the
342
327
``pub_date`` field:
352
337
 
353
338
This is shaping up well. Let's add some search capability::
354
339
 
355
 
    search_fields = ['question'],
 
340
    search_fields = ['question']
356
341
 
357
342
That adds a search box at the top of the change list. When somebody enters
358
343
search terms, Django will search the ``question`` field. You can use as many
362
347
Finally, because Poll objects have dates, it'd be convenient to be able to
363
348
drill down by date. Add this line::
364
349
 
365
 
    date_hierarchy = 'pub_date',
 
350
    date_hierarchy = 'pub_date'
366
351
 
367
352
That adds hierarchical navigation, by date, to the top of the change list page.
368
353
At top level, it displays all available years. Then it drills down to months
383
368
is powered by Django itself, and its interfaces use Django's own template
384
369
system. (How meta!)
385
370
 
386
 
Open your settings file (``myproject/settings.py``, remember) and look at the
 
371
Open your settings file (``mysite/settings.py``, remember) and look at the
387
372
``TEMPLATE_DIRS`` setting. ``TEMPLATE_DIRS`` is a tuple of filesystem
388
373
directories to check when loading Django templates. It's a search path.
389
374