Loading docs/intro/tutorial02.txt +13 −3 Original line number Diff line number Diff line Loading @@ -440,20 +440,30 @@ Open your settings file (``mysite/settings.py``, remember) and look at the filesystem directories to check when loading Django templates. It's a search path. Create a ``mytemplates`` directory in your project directory. Templates can live anywhere on your filesystem that Django can access. (Django runs as whatever user your server runs.) However, keeping your templates within the project is a good convention to follow. When you’ve done that, create a directory polls in your template directory. Within that, create a file called index.html. Note that our ``loader.get_template('polls/index.html')`` code from above maps to [template_directory]/polls/index.html” on the filesystem. By default, :setting:`TEMPLATE_DIRS` is empty. So, let's add a line to it, to tell Django where our templates live:: TEMPLATE_DIRS = ( '/home/my_username/mytemplates', # Change this to your own directory. '/path/to/mysite/mytemplates', # Change this to your own directory. ) Now copy the template ``admin/base_site.html`` from within the default Django admin template directory in the source code of Django itself (``django/contrib/admin/templates``) into an ``admin`` subdirectory of whichever directory you're using in :setting:`TEMPLATE_DIRS`. For example, if your :setting:`TEMPLATE_DIRS` includes ``'/home/my_username/mytemplates'``, as your :setting:`TEMPLATE_DIRS` includes ``'/path/to/mysite/mytemplates'``, as above, then copy ``django/contrib/admin/templates/admin/base_site.html`` to ``/home/my_username/mytemplates/admin/base_site.html``. Don't forget that ``/path/to/mysite/mytemplates/admin/base_site.html``. Don't forget that ``admin`` subdirectory. .. admonition:: Where are the Django source files? Loading docs/intro/tutorial03.txt +258 −264 File changed.Preview size limit exceeded, changes collapsed. Show changes docs/intro/tutorial04.txt +21 −87 Original line number Diff line number Diff line Loading @@ -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 }}" /> Loading @@ -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 Loading @@ -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): Loading @@ -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: Loading Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading Loading @@ -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 Loading @@ -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: Loading @@ -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 Loading Loading @@ -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>`. Loading
docs/intro/tutorial02.txt +13 −3 Original line number Diff line number Diff line Loading @@ -440,20 +440,30 @@ Open your settings file (``mysite/settings.py``, remember) and look at the filesystem directories to check when loading Django templates. It's a search path. Create a ``mytemplates`` directory in your project directory. Templates can live anywhere on your filesystem that Django can access. (Django runs as whatever user your server runs.) However, keeping your templates within the project is a good convention to follow. When you’ve done that, create a directory polls in your template directory. Within that, create a file called index.html. Note that our ``loader.get_template('polls/index.html')`` code from above maps to [template_directory]/polls/index.html” on the filesystem. By default, :setting:`TEMPLATE_DIRS` is empty. So, let's add a line to it, to tell Django where our templates live:: TEMPLATE_DIRS = ( '/home/my_username/mytemplates', # Change this to your own directory. '/path/to/mysite/mytemplates', # Change this to your own directory. ) Now copy the template ``admin/base_site.html`` from within the default Django admin template directory in the source code of Django itself (``django/contrib/admin/templates``) into an ``admin`` subdirectory of whichever directory you're using in :setting:`TEMPLATE_DIRS`. For example, if your :setting:`TEMPLATE_DIRS` includes ``'/home/my_username/mytemplates'``, as your :setting:`TEMPLATE_DIRS` includes ``'/path/to/mysite/mytemplates'``, as above, then copy ``django/contrib/admin/templates/admin/base_site.html`` to ``/home/my_username/mytemplates/admin/base_site.html``. Don't forget that ``/path/to/mysite/mytemplates/admin/base_site.html``. Don't forget that ``admin`` subdirectory. .. admonition:: Where are the Django source files? Loading
docs/intro/tutorial03.txt +258 −264 File changed.Preview size limit exceeded, changes collapsed. Show changes
docs/intro/tutorial04.txt +21 −87 Original line number Diff line number Diff line Loading @@ -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 }}" /> Loading @@ -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 Loading @@ -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): Loading @@ -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: Loading Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading Loading @@ -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 Loading @@ -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: Loading @@ -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 Loading Loading @@ -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>`.