parts/django/docs/intro/tutorial02.txt
changeset 69 c6bca38c1cbf
equal deleted inserted replaced
68:5ff1fc726848 69:c6bca38c1cbf
       
     1 =====================================
       
     2 Writing your first Django app, part 2
       
     3 =====================================
       
     4 
       
     5 This tutorial begins where :doc:`Tutorial 1 </intro/tutorial01>` left off. We're
       
     6 continuing the Web-poll application and will focus on Django's
       
     7 automatically-generated admin site.
       
     8 
       
     9 .. admonition:: Philosophy
       
    10 
       
    11     Generating admin sites for your staff or clients to add, change and delete
       
    12     content is tedious work that doesn't require much creativity. For that
       
    13     reason, Django entirely automates creation of admin interfaces for models.
       
    14 
       
    15     Django was written in a newsroom environment, with a very clear separation
       
    16     between "content publishers" and the "public" site. Site managers use the
       
    17     system to add news stories, events, sports scores, etc., and that content is
       
    18     displayed on the public site. Django solves the problem of creating a
       
    19     unified interface for site administrators to edit content.
       
    20 
       
    21     The admin isn't necessarily intended to be used by site visitors; it's for
       
    22     site managers.
       
    23 
       
    24 Activate the admin site
       
    25 =======================
       
    26 
       
    27 The Django admin site is not activated by default -- it's an opt-in thing. To
       
    28 activate the admin site for your installation, do these three things:
       
    29 
       
    30     * Add ``"django.contrib.admin"`` to your :setting:`INSTALLED_APPS` setting.
       
    31 
       
    32     * Run ``python manage.py syncdb``. Since you have added a new application
       
    33       to :setting:`INSTALLED_APPS`, the database tables need to be updated.
       
    34 
       
    35     * Edit your ``mysite/urls.py`` file and uncomment the lines that reference
       
    36       the admin -- there are three lines in total to uncomment. This file is a
       
    37       URLconf; we'll dig into URLconfs in the next tutorial. For now, all you
       
    38       need to know is that it maps URL roots to applications. In the end, you
       
    39       should have a ``urls.py`` file that looks like this:
       
    40 
       
    41     .. versionchanged:: 1.1
       
    42         The method for adding admin urls has changed in Django 1.1.
       
    43 
       
    44       .. parsed-literal::
       
    45 
       
    46           from django.conf.urls.defaults import *
       
    47 
       
    48           # Uncomment the next two lines to enable the admin:
       
    49           **from django.contrib import admin**
       
    50           **admin.autodiscover()**
       
    51 
       
    52           urlpatterns = patterns('',
       
    53               # Example:
       
    54               # (r'^mysite/', include('mysite.foo.urls')),
       
    55 
       
    56               # Uncomment the admin/doc line below and add 'django.contrib.admindocs'
       
    57               # to INSTALLED_APPS to enable admin documentation:
       
    58               # (r'^admin/doc/', include('django.contrib.admindocs.urls')),
       
    59 
       
    60               # Uncomment the next line to enable the admin:
       
    61               **(r'^admin/', include(admin.site.urls)),**
       
    62           )
       
    63 
       
    64       (The bold lines are the ones that needed to be uncommented.)
       
    65 
       
    66 Start the development server
       
    67 ============================
       
    68 
       
    69 Let's start the development server and explore the admin site.
       
    70 
       
    71 Recall from Tutorial 1 that you start the development server like so:
       
    72 
       
    73 .. code-block:: bash
       
    74 
       
    75     python manage.py runserver
       
    76 
       
    77 Now, open a Web browser and go to "/admin/" on your local domain -- e.g.,
       
    78 http://127.0.0.1:8000/admin/. You should see the admin's login screen:
       
    79 
       
    80 .. image:: _images/admin01.png
       
    81    :alt: Django admin login screen
       
    82 
       
    83 Enter the admin site
       
    84 ====================
       
    85 
       
    86 Now, try logging in. (You created a superuser account in the first part of this
       
    87 tutorial, remember?  If you didn't create one or forgot the password you can
       
    88 :ref:`create another one <topics-auth-creating-superusers>`.) You should see
       
    89 the Django admin index page:
       
    90 
       
    91 .. image:: _images/admin02t.png
       
    92    :alt: Django admin index page
       
    93 
       
    94 You should see a few other types of editable content, including groups, users
       
    95 and sites. These are core features Django ships with by default.
       
    96 
       
    97 Make the poll app modifiable in the admin
       
    98 =========================================
       
    99 
       
   100 But where's our poll app? It's not displayed on the admin index page.
       
   101 
       
   102 Just one thing to do: We need to tell the admin that ``Poll``
       
   103 objects have an admin interface. To do this, create a file called
       
   104 ``admin.py`` in your ``polls`` directory, and edit it to look like this::
       
   105 
       
   106     from polls.models import Poll
       
   107     from django.contrib import admin
       
   108 
       
   109     admin.site.register(Poll)
       
   110 
       
   111 You'll need to restart the development server to see your changes. Normally,
       
   112 the server auto-reloads code every time you modify a file, but the action of
       
   113 creating a new file doesn't trigger the auto-reloading logic.
       
   114 
       
   115 Explore the free admin functionality
       
   116 ====================================
       
   117 
       
   118 Now that we've registered ``Poll``, Django knows that it should be displayed on
       
   119 the admin index page:
       
   120 
       
   121 .. image:: _images/admin03t.png
       
   122    :alt: Django admin index page, now with polls displayed
       
   123 
       
   124 Click "Polls." Now you're at the "change list" page for polls. This page
       
   125 displays all the polls in the database and lets you choose one to change it.
       
   126 There's the "What's up?" poll we created in the first tutorial:
       
   127 
       
   128 .. image:: _images/admin04t.png
       
   129    :alt: Polls change list page
       
   130 
       
   131 Click the "What's up?" poll to edit it:
       
   132 
       
   133 .. image:: _images/admin05t.png
       
   134    :alt: Editing form for poll object
       
   135 
       
   136 Things to note here:
       
   137 
       
   138     * The form is automatically generated from the Poll model.
       
   139 
       
   140     * The different model field types (:class:`~django.db.models.DateTimeField`,
       
   141       :class:`~django.db.models.CharField`) correspond to the appropriate HTML
       
   142       input widget. Each type of field knows how to display itself in the Django
       
   143       admin.
       
   144 
       
   145     * Each :class:`~django.db.models.DateTimeField` gets free JavaScript
       
   146       shortcuts. Dates get a "Today" shortcut and calendar popup, and times get
       
   147       a "Now" shortcut and a convenient popup that lists commonly entered times.
       
   148 
       
   149 The bottom part of the page gives you a couple of options:
       
   150 
       
   151     * Save -- Saves changes and returns to the change-list page for this type of
       
   152       object.
       
   153 
       
   154     * Save and continue editing -- Saves changes and reloads the admin page for
       
   155       this object.
       
   156 
       
   157     * Save and add another -- Saves changes and loads a new, blank form for this
       
   158       type of object.
       
   159 
       
   160     * Delete -- Displays a delete confirmation page.
       
   161 
       
   162 Change the "Date published" by clicking the "Today" and "Now" shortcuts. Then
       
   163 click "Save and continue editing." Then click "History" in the upper right.
       
   164 You'll see a page listing all changes made to this object via the Django admin,
       
   165 with the timestamp and username of the person who made the change:
       
   166 
       
   167 .. image:: _images/admin06t.png
       
   168    :alt: History page for poll object
       
   169 
       
   170 Customize the admin form
       
   171 ========================
       
   172 
       
   173 Take a few minutes to marvel at all the code you didn't have to write. By
       
   174 registering the Poll model with ``admin.site.register(Poll)``, Django was able
       
   175 to construct a default form representation. Often, you'll want to customize how
       
   176 the admin form looks and works. You'll do this by telling Django the options
       
   177 you want when you register the object.
       
   178 
       
   179 Let's see how this works by re-ordering the fields on the edit form. Replace
       
   180 the ``admin.site.register(Poll)`` line with::
       
   181 
       
   182     class PollAdmin(admin.ModelAdmin):
       
   183         fields = ['pub_date', 'question']
       
   184 
       
   185     admin.site.register(Poll, PollAdmin)
       
   186 
       
   187 You'll follow this pattern -- create a model admin object, then pass it as the
       
   188 second argument to ``admin.site.register()`` -- any time you need to change the
       
   189 admin options for an object.
       
   190 
       
   191 This particular change above makes the "Publication date" come before the
       
   192 "Question" field:
       
   193 
       
   194 .. image:: _images/admin07.png
       
   195    :alt: Fields have been reordered
       
   196 
       
   197 This isn't impressive with only two fields, but for admin forms with dozens
       
   198 of fields, choosing an intuitive order is an important usability detail.
       
   199 
       
   200 And speaking of forms with dozens of fields, you might want to split the form
       
   201 up into fieldsets::
       
   202 
       
   203     class PollAdmin(admin.ModelAdmin):
       
   204         fieldsets = [
       
   205             (None,               {'fields': ['question']}),
       
   206             ('Date information', {'fields': ['pub_date']}),
       
   207         ]
       
   208 
       
   209     admin.site.register(Poll, PollAdmin)
       
   210 
       
   211 The first element of each tuple in ``fieldsets`` is the title of the fieldset.
       
   212 Here's what our form looks like now:
       
   213 
       
   214 .. image:: _images/admin08t.png
       
   215    :alt: Form has fieldsets now
       
   216 
       
   217 You can assign arbitrary HTML classes to each fieldset. Django provides a
       
   218 ``"collapse"`` class that displays a particular fieldset initially collapsed.
       
   219 This is useful when you have a long form that contains a number of fields that
       
   220 aren't commonly used::
       
   221 
       
   222         class PollAdmin(admin.ModelAdmin):
       
   223             fieldsets = [
       
   224                 (None,               {'fields': ['question']}),
       
   225                 ('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}),
       
   226             ]
       
   227 
       
   228 .. image:: _images/admin09.png
       
   229    :alt: Fieldset is initially collapsed
       
   230 
       
   231 Adding related objects
       
   232 ======================
       
   233 
       
   234 OK, we have our Poll admin page. But a ``Poll`` has multiple ``Choices``, and
       
   235 the admin page doesn't display choices.
       
   236 
       
   237 Yet.
       
   238 
       
   239 There are two ways to solve this problem. The first is to register ``Choice``
       
   240 with the admin just as we did with ``Poll``. That's easy::
       
   241 
       
   242     from polls.models import Choice
       
   243 
       
   244     admin.site.register(Choice)
       
   245 
       
   246 Now "Choices" is an available option in the Django admin. The "Add choice" form
       
   247 looks like this:
       
   248 
       
   249 .. image:: _images/admin10.png
       
   250    :alt: Choice admin page
       
   251 
       
   252 In that form, the "Poll" field is a select box containing every poll in the
       
   253 database. Django knows that a :class:`~django.db.models.ForeignKey` should be
       
   254 represented in the admin as a ``<select>`` box. In our case, only one poll
       
   255 exists at this point.
       
   256 
       
   257 Also note the "Add Another" link next to "Poll." Every object with a
       
   258 ``ForeignKey`` relationship to another gets this for free. When you click "Add
       
   259 Another," you'll get a popup window with the "Add poll" form. If you add a poll
       
   260 in that window and click "Save," Django will save the poll to the database and
       
   261 dynamically add it as the selected choice on the "Add choice" form you're
       
   262 looking at.
       
   263 
       
   264 But, really, this is an inefficient way of adding Choice objects to the system.
       
   265 It'd be better if you could add a bunch of Choices directly when you create the
       
   266 Poll object. Let's make that happen.
       
   267 
       
   268 Remove the ``register()`` call for the Choice model. Then, edit the ``Poll``
       
   269 registration code to read::
       
   270 
       
   271     class ChoiceInline(admin.StackedInline):
       
   272         model = Choice
       
   273         extra = 3
       
   274 
       
   275     class PollAdmin(admin.ModelAdmin):
       
   276         fieldsets = [
       
   277             (None,               {'fields': ['question']}),
       
   278             ('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}),
       
   279         ]
       
   280         inlines = [ChoiceInline]
       
   281 
       
   282     admin.site.register(Poll, PollAdmin)
       
   283 
       
   284 This tells Django: "Choice objects are edited on the Poll admin page. By
       
   285 default, provide enough fields for 3 choices."
       
   286 
       
   287 Load the "Add poll" page to see how that looks, you may need to restart your development server:
       
   288 
       
   289 .. image:: _images/admin11t.png
       
   290    :alt: Add poll page now has choices on it
       
   291 
       
   292 It works like this: There are three slots for related Choices -- as specified
       
   293 by ``extra`` -- and each time you come back to the "Change" page for an
       
   294 already-created object, you get another three extra slots.
       
   295 
       
   296 One small problem, though. It takes a lot of screen space to display all the
       
   297 fields for entering related Choice objects. For that reason, Django offers a
       
   298 tabular way of displaying inline related objects; you just need to change
       
   299 the ``ChoiceInline`` declaration to read::
       
   300 
       
   301     class ChoiceInline(admin.TabularInline):
       
   302         #...
       
   303 
       
   304 With that ``TabularInline`` (instead of ``StackedInline``), the
       
   305 related objects are displayed in a more compact, table-based format:
       
   306 
       
   307 .. image:: _images/admin12.png
       
   308    :alt: Add poll page now has more compact choices
       
   309 
       
   310 Customize the admin change list
       
   311 ===============================
       
   312 
       
   313 Now that the Poll admin page is looking good, let's make some tweaks to the
       
   314 "change list" page -- the one that displays all the polls in the system.
       
   315 
       
   316 Here's what it looks like at this point:
       
   317 
       
   318 .. image:: _images/admin04t.png
       
   319    :alt: Polls change list page
       
   320 
       
   321 By default, Django displays the ``str()`` of each object. But sometimes it'd be
       
   322 more helpful if we could display individual fields. To do that, use the
       
   323 ``list_display`` admin option, which is a tuple of field names to display, as
       
   324 columns, on the change list page for the object::
       
   325 
       
   326     class PollAdmin(admin.ModelAdmin):
       
   327         # ...
       
   328         list_display = ('question', 'pub_date')
       
   329 
       
   330 Just for good measure, let's also include the ``was_published_today`` custom
       
   331 method from Tutorial 1::
       
   332 
       
   333     class PollAdmin(admin.ModelAdmin):
       
   334         # ...
       
   335         list_display = ('question', 'pub_date', 'was_published_today')
       
   336 
       
   337 Now the poll change list page looks like this:
       
   338 
       
   339 .. image:: _images/admin13t.png
       
   340    :alt: Polls change list page, updated
       
   341 
       
   342 You can click on the column headers to sort by those values -- except in the
       
   343 case of the ``was_published_today`` header, because sorting by the output of
       
   344 an arbitrary method is not supported. Also note that the column header for
       
   345 ``was_published_today`` is, by default, the name of the method (with
       
   346 underscores replaced with spaces). But you can change that by giving that
       
   347 method (in ``models.py``) a ``short_description`` attribute::
       
   348 
       
   349     def was_published_today(self):
       
   350         return self.pub_date.date() == datetime.date.today()
       
   351     was_published_today.short_description = 'Published today?'
       
   352 
       
   353 Edit your admin.py file again and add an improvement to the Poll change list page: Filters. Add the
       
   354 following line to ``PollAdmin``::
       
   355 
       
   356     list_filter = ['pub_date']
       
   357 
       
   358 That adds a "Filter" sidebar that lets people filter the change list by the
       
   359 ``pub_date`` field:
       
   360 
       
   361 .. image:: _images/admin14t.png
       
   362    :alt: Polls change list page, updated
       
   363 
       
   364 The type of filter displayed depends on the type of field you're filtering on.
       
   365 Because ``pub_date`` is a DateTimeField, Django knows to give the default
       
   366 filter options for DateTimeFields: "Any date," "Today," "Past 7 days,"
       
   367 "This month," "This year."
       
   368 
       
   369 This is shaping up well. Let's add some search capability::
       
   370 
       
   371     search_fields = ['question']
       
   372 
       
   373 That adds a search box at the top of the change list. When somebody enters
       
   374 search terms, Django will search the ``question`` field. You can use as many
       
   375 fields as you'd like -- although because it uses a ``LIKE`` query behind the
       
   376 scenes, keep it reasonable, to keep your database happy.
       
   377 
       
   378 Finally, because Poll objects have dates, it'd be convenient to be able to
       
   379 drill down by date. Add this line::
       
   380 
       
   381     date_hierarchy = 'pub_date'
       
   382 
       
   383 That adds hierarchical navigation, by date, to the top of the change list page.
       
   384 At top level, it displays all available years. Then it drills down to months
       
   385 and, ultimately, days.
       
   386 
       
   387 Now's also a good time to note that change lists give you free pagination. The
       
   388 default is to display 50 items per page. Change-list pagination, search boxes,
       
   389 filters, date-hierarchies and column-header-ordering all work together like you
       
   390 think they should.
       
   391 
       
   392 Customize the admin look and feel
       
   393 =================================
       
   394 
       
   395 Clearly, having "Django administration" at the top of each admin page is
       
   396 ridiculous. It's just placeholder text.
       
   397 
       
   398 That's easy to change, though, using Django's template system. The Django admin
       
   399 is powered by Django itself, and its interfaces use Django's own template
       
   400 system.
       
   401 
       
   402 Open your settings file (``mysite/settings.py``, remember) and look at the
       
   403 :setting:`TEMPLATE_DIRS` setting. :setting:`TEMPLATE_DIRS` is a tuple of
       
   404 filesystem directories to check when loading Django templates. It's a search
       
   405 path.
       
   406 
       
   407 By default, :setting:`TEMPLATE_DIRS` is empty. So, let's add a line to it, to
       
   408 tell Django where our templates live::
       
   409 
       
   410     TEMPLATE_DIRS = (
       
   411         "/home/my_username/mytemplates", # Change this to your own directory.
       
   412     )
       
   413 
       
   414 Now copy the template ``admin/base_site.html`` from within the default Django
       
   415 admin template directory in the source code of Django itself
       
   416 (``django/contrib/admin/templates``) into an ``admin`` subdirectory of
       
   417 whichever directory you're using in :setting:`TEMPLATE_DIRS`. For example, if
       
   418 your :setting:`TEMPLATE_DIRS` includes ``"/home/my_username/mytemplates"``, as
       
   419 above, then copy ``django/contrib/admin/templates/admin/base_site.html`` to
       
   420 ``/home/my_username/mytemplates/admin/base_site.html``. Don't forget that
       
   421 ``admin`` subdirectory.
       
   422 
       
   423 Then, just edit the file and replace the generic Django text with your own
       
   424 site's name as you see fit.
       
   425 
       
   426 This template file contains lots of text like ``{% block branding %}``
       
   427 and ``{{ title }}``. The ``{%`` and ``{{`` tags are part of Django's
       
   428 template language. When Django renders ``admin/base_site.html``, this
       
   429 template language will be evaluated to produce the final HTML page.
       
   430 Don't worry if you can't make any sense of the template right now --
       
   431 we'll delve into Django's templating language in Tutorial 3.
       
   432 
       
   433 Note that any of Django's default admin templates can be overridden. To
       
   434 override a template, just do the same thing you did with ``base_site.html`` --
       
   435 copy it from the default directory into your custom directory, and make
       
   436 changes.
       
   437 
       
   438 Astute readers will ask: But if :setting:`TEMPLATE_DIRS` was empty by default,
       
   439 how was Django finding the default admin templates? The answer is that, by
       
   440 default, Django automatically looks for a ``templates/`` subdirectory within
       
   441 each app package, for use as a fallback. See the :ref:`template loader
       
   442 documentation <template-loaders>` for full information.
       
   443 
       
   444 Customize the admin index page
       
   445 ==============================
       
   446 
       
   447 On a similar note, you might want to customize the look and feel of the Django
       
   448 admin index page.
       
   449 
       
   450 By default, it displays all the apps in :setting:`INSTALLED_APPS` that have been
       
   451 registered with the admin application, in alphabetical order. You may want to
       
   452 make significant changes to the layout. After all, the index is probably the
       
   453 most important page of the admin, and it should be easy to use.
       
   454 
       
   455 The template to customize is ``admin/index.html``. (Do the same as with
       
   456 ``admin/base_site.html`` in the previous section -- copy it from the default
       
   457 directory to your custom template directory.) Edit the file, and you'll see it
       
   458 uses a template variable called ``app_list``. That variable contains every
       
   459 installed Django app. Instead of using that, you can hard-code links to
       
   460 object-specific admin pages in whatever way you think is best. Again,
       
   461 don't worry if you can't understand the template language -- we'll cover that
       
   462 in more detail in Tutorial 3.
       
   463 
       
   464 When you're comfortable with the admin site, read :doc:`part 3 of this tutorial
       
   465 </intro/tutorial03>` to start working on public poll views.