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