mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Changed overview and tutorial docs to use render_to_response and get_object_or_404, to cut down on code
git-svn-id: http://code.djangoproject.com/svn/django/trunk@678 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
		| @@ -195,20 +195,10 @@ Generally, a view retrieves data according to the parameters, loads a template | ||||
| and renders the template with the retrieved data. Here's an example view for | ||||
| article_detail from above:: | ||||
|  | ||||
|     from django.models.news import articles | ||||
|  | ||||
|     def article_detail(request, year, month, article_id): | ||||
|         # Use the Django API to find an object matching the URL criteria. | ||||
|         try: | ||||
|             a = articles.get_object(pub_date__year=year, pub_date__month=month, pk=article_id) | ||||
|         except articles.ArticleDoesNotExist: | ||||
|             raise Http404 | ||||
|         t = template_loader.get_template('news/article_detail') | ||||
|         c = Context(request, { | ||||
|             'article': a, | ||||
|         }) | ||||
|         content = t.render(c) | ||||
|         return HttpResponse(content) | ||||
|         a = get_object_or_404(articles, pub_date__year=year, pub_date__month=month, pk=article_id) | ||||
|         return render_to_response('news/article_detail', {'article': a}) | ||||
|  | ||||
| This example uses Django's template system, which has several key features. | ||||
|  | ||||
| @@ -261,7 +251,6 @@ template has to define only what's unique to that template. | ||||
|  | ||||
| Here's what the "base" template might look like:: | ||||
|  | ||||
|  | ||||
|     <html> | ||||
|     <head> | ||||
|         <title>{% block title %}{% endblock %}</title> | ||||
|   | ||||
| @@ -192,14 +192,14 @@ you want to change the way the page looks, you'll have to edit this Python code. | ||||
| So let's use Django's template system to separate the design from Python:: | ||||
|  | ||||
|     from django.core import template_loader | ||||
|     from django.core.extensions import DjangoContext as Context | ||||
|     from django.core.template import Context | ||||
|     from django.models.polls import polls | ||||
|     from django.utils.httpwrappers import HttpResponse | ||||
|  | ||||
|     def index(request): | ||||
|         latest_poll_list = polls.get_list(order_by=['-pub_date'], limit=5) | ||||
|         t = template_loader.get_template('polls/index') | ||||
|         c = Context(request, { | ||||
|         c = Context({ | ||||
|             'latest_poll_list': latest_poll_list, | ||||
|         }) | ||||
|         return HttpResponse(t.render(c)) | ||||
| @@ -242,6 +242,27 @@ Put the following code in that template:: | ||||
| Load the page in your Web browser, and you should see a bulleted-list | ||||
| containing the "What's up" poll from Tutorial 1. | ||||
|  | ||||
| A shortcut: render_to_response() | ||||
| -------------------------------- | ||||
|  | ||||
| It's a very common idiom to load a template, fill a context and return an | ||||
| ``HttpResponse`` object with the result of the rendered template. Django | ||||
| provides a shortcut. Here's the full ``index()`` view, rewritten:: | ||||
|  | ||||
|     from django.core.extensions import render_to_response | ||||
|     from django.models.polls import polls | ||||
|  | ||||
|     def index(request): | ||||
|         latest_poll_list = polls.get_list(order_by=['-pub_date'], limit=5) | ||||
|         return render_to_response('polls/index', {'latest_poll_list': latest_poll_list}) | ||||
|  | ||||
| Note that we no longer need to import ``template_loader``, ``Context`` or | ||||
| ``HttpResponse``. | ||||
|  | ||||
| The ``render_to_response()`` function takes a template name as its first | ||||
| argument and a dictionary as its optional second argument. It returns an | ||||
| ``HttpResponse`` object of the given template rendered with the given context. | ||||
|  | ||||
| Raising 404 | ||||
| =========== | ||||
|  | ||||
| @@ -254,15 +275,41 @@ for a given poll. Here's the view:: | ||||
|             p = polls.get_object(pk=poll_id) | ||||
|         except polls.PollDoesNotExist: | ||||
|             raise Http404 | ||||
|         t = template_loader.get_template('polls/detail') | ||||
|         c = Context(request, { | ||||
|             'poll': p, | ||||
|         }) | ||||
|         return HttpResponse(t.render(c)) | ||||
|         return render_to_response('polls/detail', {'poll': p}) | ||||
|  | ||||
| The new concept here: The view raises the ``django.core.exceptions.Http404`` | ||||
| exception if a poll with the requested ID doesn't exist. | ||||
|  | ||||
| A shortcut: get_object_or_404() | ||||
| ------------------------------- | ||||
|  | ||||
| It's a very common idiom to use ``get_object()`` and raise ``Http404`` if the | ||||
| object doesn't exist. Django provides a shortcut. Here's the ``detail()`` view, | ||||
| rewritten: | ||||
|  | ||||
|     from django.core.extensions import get_object_or_404 | ||||
|     def detail(request, poll_id): | ||||
|         p = get_object_or_404(polls, pk=poll_id) | ||||
|         return render_to_response('polls/detail', {'poll': p}) | ||||
|  | ||||
| The ``get_object_or_404()`` function takes a Django model module as its first | ||||
| argument and an arbitrary number of keyword arguments, which it passes to the | ||||
| module's ``get_object()`` function. It raises ``Http404`` if the object doesn't | ||||
| exist. | ||||
|  | ||||
| .. admonition:: Philosophy | ||||
|  | ||||
|     Why do we use a helper function ``get_object_or_404()`` instead of | ||||
|     automatically catching the ``*DoesNotExist`` exceptions at a higher level, | ||||
|     or having the model API raise ``Http404`` instead of ``*DoesNotExist``? | ||||
|  | ||||
|     Because that would couple the model layer to the view layer. One of the | ||||
|     foremost design goals of Django is to maintain loose coupling. | ||||
|  | ||||
| There's also a ``get_list_or_404()`` function, which works just as | ||||
| ``get_object_or_404()`` -- except using ``get_list()`` instead of | ||||
| ``get_object()``. It raises ``Http404`` if the list is empty. | ||||
|  | ||||
| Write a 404 (page not found) view | ||||
| ================================= | ||||
|  | ||||
|   | ||||
| @@ -48,27 +48,20 @@ included this line:: | ||||
|  | ||||
| So let's create a ``vote()`` function in ``myproject/apps/polls/views/polls.py``:: | ||||
|  | ||||
|     from django.core import template_loader | ||||
|     from django.core.extensions import DjangoContext as Context | ||||
|     from django.core.extensions import get_object_or_404, render_to_response | ||||
|     from django.models.polls import choices, polls | ||||
|     from django.utils.httpwrappers import HttpResponse, HttpResponseRedirect | ||||
|     from django.core.exceptions import Http404 | ||||
|     from django.utils.httpwrappers import HttpResponseRedirect | ||||
|  | ||||
|     def vote(request, poll_id): | ||||
|         try: | ||||
|             p = polls.get_object(pk=poll_id) | ||||
|         except polls.PollDoesNotExist: | ||||
|             raise Http404 | ||||
|         p = get_object_or_404(polls, pk=poll_id) | ||||
|         try: | ||||
|             selected_choice = p.get_choice(pk=request.POST['choice']) | ||||
|         except (KeyError, choices.ChoiceDoesNotExist): | ||||
|             # Redisplay the poll voting form. | ||||
|             t = template_loader.get_template('polls/detail') | ||||
|             c = Context(request, { | ||||
|             return render_to_response('polls/detail', { | ||||
|                 'poll': p, | ||||
|                 'error_message': "You didn't select a choice.", | ||||
|             }) | ||||
|             return HttpResponse(t.render(c)) | ||||
|         else: | ||||
|             selected_choice.votes += 1 | ||||
|             selected_choice.save() | ||||
| @@ -109,15 +102,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): | ||||
|         try: | ||||
|             p = polls.get_object(pk=poll_id) | ||||
|         except polls.PollDoesNotExist: | ||||
|             raise Http404 | ||||
|         t = template_loader.get_template('polls/results') | ||||
|         c = Context(request, { | ||||
|             'poll': p, | ||||
|         }) | ||||
|         return HttpResponse(t.render(c)) | ||||
|         p = get_object_or_404(polls, pk=poll_id) | ||||
|         return render_to_response('polls/results', {'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. | ||||
|   | ||||
		Reference in New Issue
	
	Block a user