| | 348 | Customize the admin change list |
|---|
| | 349 | =============================== |
|---|
| | 350 | |
|---|
| | 351 | Now that the Poll admin page is looking good, let's make some tweaks to the |
|---|
| | 352 | "change list" page -- the one that displays all the polls in the system. |
|---|
| | 353 | |
|---|
| | 354 | Here's what it looks like at this point: |
|---|
| | 355 | |
|---|
| | 356 | .. image:: http://media.djangoproject.com/img/doc/tutorial/admin04t.png |
|---|
| | 357 | :alt: Polls change list page |
|---|
| | 358 | :target: http://media.djangoproject.com/img/doc/tutorial/admin04.png |
|---|
| | 359 | |
|---|
| | 360 | By default, Django displays the ``repr()`` of each object. But it'd be more |
|---|
| | 361 | helpful if we could display individual fields. To do that, use the |
|---|
| | 362 | ``list_display`` option, which is a tuple of field names to display, as columns, |
|---|
| | 363 | on the change list page for the object:: |
|---|
| | 364 | |
|---|
| | 365 | class Poll(meta.Model): |
|---|
| | 366 | # ... |
|---|
| | 367 | admin = meta.Admin( |
|---|
| | 368 | fields = ( |
|---|
| | 369 | (None, {'fields': ('question', 'pub_date')}), |
|---|
| | 370 | ), |
|---|
| | 371 | list_display = ('question', 'pub_date'), |
|---|
| | 372 | ) |
|---|
| | 373 | |
|---|
| | 374 | Just for good measure, let's also include the ``was_published_today`` custom |
|---|
| | 375 | method from Tutorial 1:: |
|---|
| | 376 | |
|---|
| | 377 | list_display = ('question', 'pub_date', 'was_published_today'), |
|---|
| | 378 | |
|---|
| | 379 | Now the poll change list page looks like this: |
|---|
| | 380 | |
|---|
| | 381 | .. image:: http://media.djangoproject.com/img/doc/tutorial/admin13t.png |
|---|
| | 382 | :alt: Polls change list page, updated |
|---|
| | 383 | :target: http://media.djangoproject.com/img/doc/tutorial/admin13.png |
|---|
| | 384 | |
|---|
| | 385 | You can click on the column headers to sort by those values -- except in the |
|---|
| | 386 | case of the ``was_published_today`` header, because sorting by the output of |
|---|
| | 387 | an arbitrary method is not supported. Also note that the column header for |
|---|
| | 388 | ``was_published_today`` is, by default, the name of the method. But you can |
|---|
| | 389 | change that by giving that method a ``short_description`` attribute:: |
|---|
| | 390 | |
|---|
| | 391 | def was_published_today(self): |
|---|
| | 392 | return self.pub_date.date() == datetime.date.today() |
|---|
| | 393 | was_published_today.short_description = 'Was published today' |
|---|
| | 394 | |
|---|
| | 395 | |
|---|
| | 396 | Let's add another improvement to the Poll change list page: Filters. Add the |
|---|
| | 397 | following line to ``Poll.admin``: |
|---|
| | 398 | |
|---|
| | 399 | list_filter = ('pub_date', ) |
|---|
| | 400 | |
|---|
| | 401 | That adds a "Filter" sidebar that lets people filter the change list by the |
|---|
| | 402 | ``pub_date`` field: |
|---|
| | 403 | |
|---|
| | 404 | .. image:: http://media.djangoproject.com/img/doc/tutorial/admin14t.png |
|---|
| | 405 | :alt: Polls change list page, updated |
|---|
| | 406 | :target: http://media.djangoproject.com/img/doc/tutorial/admin14.png |
|---|
| | 407 | |
|---|
| | 408 | The type of filter displayed depends on the type of field you're filtering on. |
|---|
| | 409 | Because ``pub_date`` is a DateTimeField, Django knows to give the default |
|---|
| | 410 | filter options for DateTimeFields: "Any date," "Today," "Past 7 days," |
|---|
| | 411 | "This month," "This year." Explore using ``list_filter`` on other types of |
|---|
| | 412 | fields. |
|---|
| | 413 | |
|---|
| | 414 | This is shaping up well. Finally, let's add some search capability: |
|---|
| | 415 | |
|---|
| | 416 | search_fields = ('question', ) |
|---|
| | 417 | |
|---|
| | 418 | That adds a search box at the top of the change list. When somebody enters |
|---|
| | 419 | search terms, Django will search the ``question`` field. You can use as many |
|---|
| | 420 | fields as you'd like -- although because it uses a LIKE query behind the |
|---|
| | 421 | scenes, keep it reasonable to mind your database performance. |
|---|
| | 422 | |
|---|
| | 423 | Finally, because Poll objects have dates, it'd be convenient to be able to |
|---|
| | 424 | drill down by date. Add this line:: |
|---|
| | 425 | |
|---|
| | 426 | date_hierarchy = 'pub_date', |
|---|
| | 427 | |
|---|
| | 428 | That adds hierarchical navigation, by date, to the top of the change list page. |
|---|
| | 429 | At top level, it displays all available years. Then it drills down to months |
|---|
| | 430 | and, ultimately, days. |
|---|
| | 431 | |
|---|
| | 432 | Now's also a good time to note that change lists give you free pagination. The |
|---|
| | 433 | default is to display 50 items per page. Change-list pagination, search boxes, |
|---|
| | 434 | filters, date-hierarchies and column-header-ordering all work together like you |
|---|
| | 435 | think they should. |
|---|
| | 436 | |
|---|