diff options
| author | Derek Anderson <public@kered.org> | 2007-07-20 20:49:49 +0000 |
|---|---|---|
| committer | Derek Anderson <public@kered.org> | 2007-07-20 20:49:49 +0000 |
| commit | 365f4b869800469ba786919f11422c73b3ec9fbb (patch) | |
| tree | bc45d8db548a35b99c54600e0c4fde9ca87b35bc /docs/tutorial04.txt | |
| parent | 42851d90dadbf62f5d342ce5c4f496ba1eeba987 (diff) | |
schema-evolution: merged trunk:HEAD into schema-evolution branch
git-svn-id: http://code.djangoproject.com/svn/django/branches/schema-evolution@5734 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'docs/tutorial04.txt')
| -rw-r--r-- | docs/tutorial04.txt | 70 |
1 files changed, 61 insertions, 9 deletions
diff --git a/docs/tutorial04.txt b/docs/tutorial04.txt index c5e2ea3cea..cfd9a45a4b 100644 --- a/docs/tutorial04.txt +++ b/docs/tutorial04.txt @@ -48,6 +48,7 @@ So let's create a ``vote()`` function in ``mysite/polls/views.py``:: from django.shortcuts import get_object_or_404, render_to_response from django.http import HttpResponseRedirect + from django.core.urlresolvers import reverse from mysite.polls.models import Choice, Poll # ... def vote(request, poll_id): @@ -66,7 +67,7 @@ So let's create a ``vote()`` function in ``mysite/polls/views.py``:: # Always return an HttpResponseRedirect after successfully dealing # with POST data. This prevents data from being posted twice if a # user hits the Back button. - return HttpResponseRedirect('/polls/%s/results/' % p.id) + return HttpResponseRedirect(reverse('mysite.polls.views.results', args=(p.id,))) This code includes a few things we haven't covered yet in this tutorial: @@ -86,13 +87,29 @@ This code includes a few things we haven't covered yet in this tutorial: * After incrementing the choice count, the code returns an ``HttpResponseRedirect`` rather than a normal ``HttpResponse``. ``HttpResponseRedirect`` takes a single argument: the URL to which the - user will be redirected. You should leave off the "http://" and domain - name if you can. That helps your app become portable across domains. + user will be redirected (see the following point for how we construct + the URL in this case). As the Python comment above points out, you should always return an ``HttpResponseRedirect`` after successfully dealing with POST data. This tip isn't specific to Django; it's just good Web development practice. + * We are using the ``reverse()`` function in the ``HttpResponseRedirect`` + constructor in this example. This function helps avoid having to + hardcode a URL in the view function. It is given the name of the view + that we want to pass control to and the variable portion of the URL + pattern that points to that view. In this case, using the URLConf we set + up in Tutorial 3, this ``reverse()`` call will return a string like :: + + '/polls/3/results/' + + ... where the ``3`` is the value of ``p.id``. This redirected URL will + then call the ``'results'`` view to display the final page. Note that + you need to use the full name of the view here (including the prefix). + + For more information about ``reverse()``, see the `URL dispatcher`_ + documentation. + As mentioned in Tutorial 3, ``request`` is a ``HTTPRequest`` object. For more on ``HTTPRequest`` objects, see the `request and response documentation`_. @@ -120,7 +137,8 @@ Now, go to ``/polls/1/`` in your browser and vote in the poll. You should see a results page that gets updated each time you vote. If you submit the form without having chosen a choice, you should see the error message. -.. _request and response documentation: http://www.djangoproject.com/documentation/request_response/ +.. _request and response documentation: ../request_response/ +.. _URL dispatcher: ../url_dispatch#reverse Use generic views: Less code is better ====================================== @@ -175,7 +193,7 @@ Change it like so:: urlpatterns = patterns('', (r'^$', 'django.views.generic.list_detail.object_list', info_dict), (r'^(?P<object_id>\d+)/$', 'django.views.generic.list_detail.object_detail', info_dict), - (r'^(?P<object_id>\d+)/results/$', 'django.views.generic.list_detail.object_detail', dict(info_dict, template_name='polls/results.html')), + (r'^(?P<object_id>\d+)/results/$', 'django.views.generic.list_detail.object_detail', dict(info_dict, template_name='polls/results.html'), 'poll_results'), (r'^(?P<poll_id>\d+)/vote/$', 'mysite.polls.views.vote'), ) @@ -191,14 +209,20 @@ objects" and "display a detail page for a particular type of object." from the URL to be called ``"object_id"``, so we've changed ``poll_id`` to ``object_id`` for the generic views. + * We've added a name, ``poll_results``, to the results view so that we have + a way to refer to its URL later on (see `naming URL patterns`_ for more on + named patterns). + +.. _naming URL patterns: http://www.djangoproject.com/documentation/url_dispatch/#naming-url-patterns + By default, the ``object_detail`` generic view uses a template called -``<app name>/<module name>_detail.html``. In our case, it'll use the template +``<app name>/<model name>_detail.html``. In our case, it'll use the template ``"polls/poll_detail.html"``. Thus, rename your ``polls/detail.html`` template to ``polls/poll_detail.html``, and change the ``render_to_response()`` line in ``vote()``. Similarly, the ``object_list`` generic view uses a template called -``<app name>/<module name>_list.html``. Thus, rename ``polls/index.html`` to +``<app name>/<model name>_list.html``. Thus, rename ``polls/index.html`` to ``polls/poll_list.html``. Because we have more than one entry in the URLconf that uses ``object_detail`` @@ -206,6 +230,21 @@ for the polls app, we manually specify a template name for the results view: ``template_name='polls/results.html'``. Otherwise, both views would use the same template. Note that we use ``dict()`` to return an altered dictionary in place. +.. note:: ``all()`` is lazy + + It might look a little frightening to see ``Poll.objects.all()`` being used + in a detail view which only needs one ``Poll`` object, but don't worry; + ``Poll.objects.all()`` is actually a special object called a ``QuerySet``, + which is "lazy" and doesn't hit your database until it absolutely has to. By + the time the database query happens, the ``object_detail`` generic view will + have narrowed its scope down to a single object, so the eventual query will + only select one row from the database. + + If you'd like to know more about how that works, The Django database API + documentation `explains the lazy nature of QuerySet objects`_. + +.. _explains the lazy nature of QuerySet objects: ../db-api/#querysets-are-lazy + In previous parts of the tutorial, the templates have been provided with a context that contains the ``poll`` and ``latest_poll_list`` context variables. However, the generic views provide the variables ``object`` and ``object_list`` as context. @@ -222,11 +261,20 @@ the new templates and context variables. Change the template call from ``polls/detail.html`` to ``polls/poll_detail.html``, and pass ``object`` in the context instead of ``poll``. +The last thing to do is fix the URL handling to account for the use of generic +views. In the vote view above, we used the ``reverse()`` function to avoid +hard-coding our URLs. Now that we've switched to a generic view, we'll need to +change the ``reverse()`` call to point back to our new generic view. We can't +simply use the view function anymore -- generic views can be (and are) used +multiple times -- but we can use the name we've given:: + + return HttpResponseRedirect(reverse('poll_results', args=(p.id,))) + Run the server, and use your new polling app based on generic views. For full details on generic views, see the `generic views documentation`_. -.. _generic views documentation: http://www.djangoproject.com/documentation/generic_views/ +.. _generic views documentation: ../generic_views/ Coming soon =========== @@ -241,4 +289,8 @@ installments: * Advanced admin features: Permissions * Advanced admin features: Custom JavaScript -.. _Tutorial 3: http://www.djangoproject.com/documentation/tutorial3/ +In the meantime, you can read through the rest of the `Django documentation`_ +and start writing your own applications. + +.. _Tutorial 3: ../tutorial03/ +.. _Django documentation: http://www.djangoproject.com/documentation/ |
