From f69cf70ed813a8cd7e1f963a14ae39103e8d5265 Mon Sep 17 00:00:00 2001 From: Adrian Holovaty Date: Tue, 2 May 2006 01:31:56 +0000 Subject: MERGED MAGIC-REMOVAL BRANCH TO TRUNK. This change is highly backwards-incompatible. Please read http://code.djangoproject.com/wiki/RemovingTheMagic for upgrade instructions. git-svn-id: http://code.djangoproject.com/svn/django/trunk@2809 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- docs/tutorial04.txt | 92 ++++++++++++++++++++++++++++------------------------- 1 file changed, 48 insertions(+), 44 deletions(-) (limited to 'docs/tutorial04.txt') diff --git a/docs/tutorial04.txt b/docs/tutorial04.txt index f6a0abb6d1..67974327a3 100644 --- a/docs/tutorial04.txt +++ b/docs/tutorial04.txt @@ -2,8 +2,6 @@ Writing your first Django app, part 4 ===================================== -By Adrian Holovaty - This tutorial begins where `Tutorial 3`_ left off. We're continuing the Web-poll application and will focus on simple form processing and cutting down our code. @@ -18,7 +16,7 @@ template contains an HTML ``
`` element:: {% if error_message %}

{{ error_message }}

{% endif %} - {% for choice in poll.get_choice_list %} + {% for choice in poll.choice_set.all %}
{% endfor %} @@ -41,24 +39,24 @@ A quick rundown: Django; it's just good Web development practice. Now, let's create a Django view that handles the submitted data and does -something with it. Remember, in `Tutorial 3`_, we create a URLconf that -included this line:: - - (r'^polls/(?P\d+)/vote/$', 'myproject.polls.views.vote'), +something with it. Remember, in `Tutorial 3`_, we created a URLconf for the +polls application that includes this line:: -So let's create a ``vote()`` function in ``myproject/polls/views.py``:: + (r'^(?P\d+)/vote/$', 'mysite.polls.views.vote'), - from django.core.extensions import get_object_or_404, render_to_response - from django.models.polls import choices, polls - from django.utils.httpwrappers import HttpResponseRedirect +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 mysite.polls.models import Choice, Poll + # ... def vote(request, poll_id): - p = get_object_or_404(polls, pk=poll_id) + p = get_object_or_404(Poll, pk=poll_id) try: - selected_choice = p.get_choice(pk=request.POST['choice']) - except (KeyError, choices.ChoiceDoesNotExist): + selected_choice = p.choice_set.get(pk=request.POST['choice']) + except (KeyError, Choice.DoesNotExist): # Redisplay the poll voting form. - return render_to_response('polls/detail', { + return render_to_response('polls/detail.html', { 'poll': p, 'error_message': "You didn't select a choice.", }) @@ -102,8 +100,8 @@ After somebody votes in a poll, the ``vote()`` view redirects to the results page for the poll. Let's write that view:: def results(request, poll_id): - p = get_object_or_404(polls, pk=poll_id) - return render_to_response('polls/results', {'poll': p}) + p = get_object_or_404(Poll, pk=poll_id) + return render_to_response('polls/results.html', {'poll': p}) This is almost exactly the same as the ``detail()`` view from `Tutorial 3`_. The only difference is the template name. We'll fix this redundancy later. @@ -113,7 +111,7 @@ Now, create a ``results.html`` template::

{{ poll.question }}

    - {% for choice in poll.get_choice_list %} + {% for choice in poll.choice_set.all %}
  • {{ choice.choice }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}
  • {% endfor %}
@@ -153,12 +151,12 @@ conversion. You should know basic math before you start using a calculator. -First, open the polls.py URLconf. It looks like this, according to the tutorial -so far:: +First, open the polls/urls.py URLconf. It looks like this, according to the +tutorial so far:: from django.conf.urls.defaults import * - urlpatterns = patterns('myproject.polls.views', + urlpatterns = patterns('mysite.polls.views', (r'^$', 'index'), (r'^(?P\d+)/$', 'detail'), (r'^(?P\d+)/results/$', 'results'), @@ -168,56 +166,62 @@ so far:: Change it like so:: from django.conf.urls.defaults import * + from mysite.polls.models import Poll info_dict = { - 'app_label': 'polls', - 'module_name': 'polls', + 'queryset': Poll.objects.all(), } urlpatterns = patterns('', (r'^$', 'django.views.generic.list_detail.object_list', info_dict), (r'^(?P\d+)/$', 'django.views.generic.list_detail.object_detail', info_dict), - (r'^(?P\d+)/results/$', 'django.views.generic.list_detail.object_detail', dict(info_dict, template_name='polls/results')), - (r'^(?P\d+)/vote/$', 'myproject.polls.views.vote'), + (r'^(?P\d+)/results/$', 'django.views.generic.list_detail.object_detail', dict(info_dict, template_name='polls/results.html')), + (r'^(?P\d+)/vote/$', 'mysite.polls.views.vote'), ) We're using two generic views here: ``object_list`` and ``object_detail``. Respectively, those two views abstract the concepts of "display a list of objects" and "display a detail page for a particular type of object." - * Each generic view needs to know which ``app_label`` and ``module_name`` - it's acting on. Thus, we've defined ``info_dict``, a dictionary that's - passed to each of the generic views via the third parameter to the URL - tuples. + * Each generic view needs to know what data it will be acting upon. This + data is provided in a dictionary. The ``queryset`` key in this dictionary + points to the list of objects to be manipulated by the generic view. - * The ``object_detail`` generic view expects that the ID value captured - from the URL is called ``"object_id"``, so we've changed ``poll_id`` to + * The ``object_detail`` generic view expects the ID value captured + from the URL to be called ``"object_id"``, so we've changed ``poll_id`` to ``object_id`` for the generic views. By default, the ``object_detail`` generic view uses a template called -``/_detail``. In our case, it'll use the template -``"polls/polls_detail"``. Thus, rename your ``polls/detail.html`` template to -``polls/polls_detail.html``, and change the ``render_to_response()`` line in +``/_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 -``/_list``. Thus, rename ``polls/index.html`` to -``polls/polls_list.html``. +``/_list.html``. Thus, rename ``poll/index.html`` to +``polls/poll_list.html``. Because we have more than one entry in the URLconf that uses ``object_detail`` for the polls app, we manually specify a template name for the results view: -``template_name='polls/results'``. Otherwise, both views would use the same +``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. -The generic views pass ``object`` and ``object_list`` to their templates, so -change your templates so that ``latest_poll_list`` becomes ``object_list`` and -``poll`` becomes ``object``. +In previous versions 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. +Therefore, you need to change your templates to match the new context variables. +Go through your templates, and modify any reference to ``latest_poll_list`` to +``object_list``, and change any reference to ``poll`` to ``object``. + +You can now delete the ``index()``, ``detail()`` and ``results()`` views +from ``polls/views.py``. We don't need them anymore -- they have been replaced +by generic views. -In the ``vote()`` view, change the template call from ``polls/detail`` to -``polls/polls_detail``, and pass ``object`` in the context instead of ``poll``. +The ``vote()`` view is still required. However, it must be modified to match +the new templates and context variables. Change the template call from ``polls/detail`` +to ``polls/polls_detail``, and pass ``object`` in the context instead of ``poll``. -Finally, you can delete the ``index()``, ``detail()`` and ``results()`` views -from ``polls/views.py``. We don't need them anymore. +Run the server, and use your new polling app based on generic views. For full details on generic views, see the `generic views documentation`_. -- cgit v1.3