summaryrefslogtreecommitdiff
path: root/docs/tutorial04.txt
diff options
context:
space:
mode:
authorDerek Anderson <public@kered.org>2007-07-20 20:49:49 +0000
committerDerek Anderson <public@kered.org>2007-07-20 20:49:49 +0000
commit365f4b869800469ba786919f11422c73b3ec9fbb (patch)
treebc45d8db548a35b99c54600e0c4fde9ca87b35bc /docs/tutorial04.txt
parent42851d90dadbf62f5d342ce5c4f496ba1eeba987 (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.txt70
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/