diff options
| author | Tim Graham <timograham@gmail.com> | 2012-10-13 14:37:39 -0400 |
|---|---|---|
| committer | Tim Graham <timograham@gmail.com> | 2012-10-15 19:47:26 -0400 |
| commit | 07abb7a6b7af2c45be553acf08d85cd2d72057ad (patch) | |
| tree | 742649553c7bb95e54cc0d6f7059d7c0fc8bcd58 /docs/intro/tutorial04.txt | |
| parent | 08286ca5d93c142a60edda5ee37b3a8a7bc72274 (diff) | |
Fixed #18715 - Refactored tutorial 3. Thank-you Daniel Greenfeld!
Diffstat (limited to 'docs/intro/tutorial04.txt')
| -rw-r--r-- | docs/intro/tutorial04.txt | 108 |
1 files changed, 21 insertions, 87 deletions
diff --git a/docs/intro/tutorial04.txt b/docs/intro/tutorial04.txt index 49e597ca29..8909caf98b 100644 --- a/docs/intro/tutorial04.txt +++ b/docs/intro/tutorial04.txt @@ -18,7 +18,7 @@ tutorial, so that the template contains an HTML ``<form>`` element: {% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %} - <form action="{% url 'polls.views.vote' poll.id %}" method="post"> + <form action="{% url 'polls:vote' poll.id %}" method="post"> {% csrf_token %} {% for choice in poll.choice_set.all %} <input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" /> @@ -35,7 +35,7 @@ A quick rundown: selects one of the radio buttons and submits the form, it'll send the POST data ``choice=3``. This is HTML Forms 101. -* We set the form's ``action`` to ``{% url 'polls.views.vote' poll.id %}``, and we +* We set the form's ``action`` to ``{% url 'polls:vote' poll.id %}``, and we set ``method="post"``. Using ``method="post"`` (as opposed to ``method="get"``) is very important, because the act of submitting this form will alter data server-side. Whenever you create a form that alters @@ -52,34 +52,18 @@ A quick rundown: forms that are targeted at internal URLs should use the :ttag:`{% csrf_token %}<csrf_token>` template tag. -The :ttag:`{% csrf_token %}<csrf_token>` tag requires information from the -request object, which is not normally accessible from within the template -context. To fix this, a small adjustment needs to be made to the ``detail`` -view, so that it looks like the following:: - - from django.template import RequestContext - # ... - def detail(request, poll_id): - p = get_object_or_404(Poll, pk=poll_id) - return render_to_response('polls/detail.html', {'poll': p}, - context_instance=RequestContext(request)) - -The details of how this works are explained in the documentation for -:ref:`RequestContext <subclassing-context-requestcontext>`. - Now, let's create a Django view that handles the submitted data and does something with it. Remember, in :doc:`Tutorial 3 </intro/tutorial03>`, we created a URLconf for the polls application that includes this line:: - (r'^(?P<poll_id>\d+)/vote/$', 'vote'), + url(r'^(?P<poll_id>\d+)/vote/$', views.vote, name='vote'), We also created a dummy implementation of the ``vote()`` function. Let's create a real version. Add the following to ``polls/views.py``:: - from django.shortcuts import get_object_or_404, render_to_response + from django.shortcuts import get_object_or_404, render from django.http import HttpResponseRedirect, HttpResponse from django.core.urlresolvers import reverse - from django.template import RequestContext from polls.models import Choice, Poll # ... def vote(request, poll_id): @@ -88,17 +72,17 @@ create a real version. Add the following to ``polls/views.py``:: 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.html', { + return render(request, 'polls/detail.html', { 'poll': p, 'error_message': "You didn't select a choice.", - }, context_instance=RequestContext(request)) + }) else: selected_choice.votes += 1 selected_choice.save() # 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(reverse('polls.views.results', args=(p.id,))) + return HttpResponseRedirect(reverse('polls:results', args=(p.id,))) This code includes a few things we haven't covered yet in this tutorial: @@ -142,8 +126,7 @@ This code includes a few things we haven't covered yet in this tutorial: '/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). + then call the ``'results'`` view to display the final page. As mentioned in Tutorial 3, ``request`` is a :class:`~django.http.HttpRequest` object. For more on :class:`~django.http.HttpRequest` objects, see the @@ -153,14 +136,14 @@ 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(Poll, pk=poll_id) - return render_to_response('polls/results.html', {'poll': p}) + poll = get_object_or_404(Poll, pk=poll_id) + return render(request, 'polls/results.html', {'poll': poll}) This is almost exactly the same as the ``detail()`` view from :doc:`Tutorial 3 </intro/tutorial03>`. The only difference is the template name. We'll fix this redundancy later. -Now, create a ``results.html`` template: +Now, create a ``polls/results.html`` template: .. code-block:: html+django @@ -172,7 +155,7 @@ Now, create a ``results.html`` template: {% endfor %} </ul> - <a href="{% url 'polls.views.detail' poll.id %}">Vote again?</a> + <a href="{% url 'polls:detail' poll.id %}">Vote again?</a> 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 @@ -215,19 +198,7 @@ Read on for details. You should know basic math before you start using a calculator. -First, open the ``polls/urls.py`` URLconf. It looks like this, according to the -tutorial so far:: - - from django.conf.urls import patterns, url - - urlpatterns = patterns('polls.views', - url(r'^$', 'index'), - url(r'^(?P<poll_id>\d+)/$', 'detail'), - url(r'^(?P<poll_id>\d+)/results/$', 'results'), - url(r'^(?P<poll_id>\d+)/vote/$', 'vote'), - ) - -Change it like so:: +First, open the ``polls/urls.py`` URLconf and change it like so:: from django.conf.urls import patterns, url from django.views.generic import DetailView, ListView @@ -239,18 +210,18 @@ Change it like so:: queryset=Poll.objects.order_by('-pub_date')[:5], context_object_name='latest_poll_list', template_name='polls/index.html'), - name='poll_index'), + name='index'), url(r'^(?P<pk>\d+)/$', DetailView.as_view( model=Poll, template_name='polls/detail.html'), - name='poll_detail'), + name='detail'), url(r'^(?P<pk>\d+)/results/$', DetailView.as_view( model=Poll, template_name='polls/results.html'), - name='poll_results'), - url(r'^(?P<poll_id>\d+)/vote/$', 'polls.views.vote'), + name='results'), + url(r'^(?P<poll_id>\d+)/vote/$', 'polls.views.vote', name='vote'), ) We're using two generic views here: @@ -267,15 +238,6 @@ two views abstract the concepts of "display a list of objects" and ``"pk"``, so we've changed ``poll_id`` to ``pk`` for the generic views. -* We've added the ``name`` argument to the views (e.g. ``name='poll_results'``) - so that we have a way to refer to their URL later on (see the - documentation about :ref:`naming URL patterns - <naming-url-patterns>` for information). We're also using the - :func:`~django.conf.urls.url` function from - :mod:`django.conf.urls` here. It's a good habit to use - :func:`~django.conf.urls.url` when you are providing a - pattern name like this. - By default, the :class:`~django.views.generic.list.DetailView` generic view uses a template called ``<app name>/<model name>_detail.html``. In our case, it'll use the template ``"polls/poll_detail.html"``. The @@ -308,41 +270,13 @@ 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. -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 -:func:`~django.core.urlresolvers.reverse` function to avoid -hard-coding our URLs. Now that we've switched to a generic view, we'll -need to change the :func:`~django.core.urlresolvers.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,))) - -The same rule apply for the :ttag:`url` template tag. For example in the -``results.html`` template: - -.. code-block:: html+django - - <a href="{% url 'poll_detail' poll.id %}">Vote again?</a> - Run the server, and use your new polling app based on generic views. For full details on generic views, see the :doc:`generic views documentation </topics/class-based-views/index>`. -Coming soon -=========== - -The tutorial ends here for the time being. Future installments of the tutorial -will cover: - -* Advanced form processing -* Using the RSS framework -* Using the cache framework -* Using the comments framework -* Advanced admin features: Permissions -* Advanced admin features: Custom JavaScript +What's next? +============ -In the meantime, you might want to check out some pointers on :doc:`where to go -from here </intro/whatsnext>` +The tutorial ends here for the time being. In the meantime, you might want to +check out some pointers on :doc:`where to go from here </intro/whatsnext>`. |
