Ticket #15008: admin-template-response.patch

File admin-template-response.patch, 24.7 KB (added by Chris Adams, 13 years ago)

Patch against r16086

  • django/contrib/admin/actions.py

    From 726c99776932147a43394dc94c06bebe86acde19 Mon Sep 17 00:00:00 2001
    From: Chris Adams <chris@improbable.org>
    Date: Mon, 3 Jan 2011 10:03:18 -0500
    Subject: [PATCH] admin, auth: replaced render_to_response with TemplateResponse
    
    * Replaced all calls to render_to_response with TemplateResponses for easier
      customization
    
    * Add TemplateResponse pointer to admin documentation
    
      The admin view customization section now mentions that the responses may be
      customized and points to the TemplateResponse documentation.
    
    * Admin view tests: verify that TemplateResponses are returned
    ---
     django/contrib/admin/actions.py            |    7 +--
     django/contrib/admin/options.py            |   30 +++++-----
     django/contrib/admin/sites.py              |   20 ++++---
     django/contrib/admin/views/decorators.py   |    2 +
     django/contrib/auth/admin.py               |    8 ++--
     django/contrib/auth/views.py               |   79 ++++++++++++++++++----------
     docs/ref/contrib/admin/index.txt           |    7 +++
     tests/regressiontests/admin_views/tests.py |   25 ++++++---
     8 files changed, 112 insertions(+), 66 deletions(-)
    
    diff --git a/django/contrib/admin/actions.py b/django/contrib/admin/actions.py
    index c68184a..f8d73c5 100644
    a b  
    22Built-in, globally-available admin actions.
    33"""
    44
    5 from django import template
    65from django.core.exceptions import PermissionDenied
    76from django.contrib.admin import helpers
    87from django.contrib.admin.util import get_deleted_objects, model_ngettext
    98from django.db import router
    10 from django.shortcuts import render_to_response
     9from django.template.response import TemplateResponse
    1110from django.utils.encoding import force_unicode
    1211from django.utils.translation import ugettext_lazy, ugettext as _
    1312
    def delete_selected(modeladmin, request, queryset):  
    7675    }
    7776
    7877    # Display the confirmation page
    79     return render_to_response(modeladmin.delete_selected_confirmation_template or [
     78    return TemplateResponse(request, modeladmin.delete_selected_confirmation_template or [
    8079        "admin/%s/%s/delete_selected_confirmation.html" % (app_label, opts.object_name.lower()),
    8180        "admin/%s/delete_selected_confirmation.html" % app_label,
    8281        "admin/delete_selected_confirmation.html"
    83     ], context, context_instance=template.RequestContext(request))
     82    ], context=context, current_app=modeladmin.admin_site.name)
    8483
    8584delete_selected.short_description = ugettext_lazy("Delete selected %(verbose_name_plural)s")
  • django/contrib/admin/options.py

    diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py
    index d08e22b..f32b207 100644
    a b  
    11from functools import update_wrapper, partial
    2 from django import forms, template
     2from django import forms
    33from django.forms.formsets import all_valid
    44from django.forms.models import (modelform_factory, modelformset_factory,
    55    inlineformset_factory, BaseInlineFormSet)
    from django.db.models.related import RelatedObject  
    1515from django.db.models.fields import BLANK_CHOICE_DASH, FieldDoesNotExist
    1616from django.db.models.sql.constants import LOOKUP_SEP, QUERY_TERMS
    1717from django.http import Http404, HttpResponse, HttpResponseRedirect
    18 from django.shortcuts import get_object_or_404, render_to_response
     18from django.shortcuts import get_object_or_404
     19from django.template.response import SimpleTemplateResponse, TemplateResponse
    1920from django.utils.decorators import method_decorator
    2021from django.utils.datastructures import SortedDict
    2122from django.utils.html import escape, escapejs
    class ModelAdmin(BaseModelAdmin):  
    708709            form_template = self.add_form_template
    709710        else:
    710711            form_template = self.change_form_template
    711         context_instance = template.RequestContext(request, current_app=self.admin_site.name)
    712         return render_to_response(form_template or [
     712
     713        return TemplateResponse(request, form_template or [
    713714            "admin/%s/%s/change_form.html" % (app_label, opts.object_name.lower()),
    714715            "admin/%s/change_form.html" % app_label,
    715716            "admin/change_form.html"
    716         ], context, context_instance=context_instance)
     717        ], context=context, current_app=self.admin_site.name)
    717718
    718719    def response_add(self, request, obj, post_url_continue='../%s/'):
    719720        """
    class ModelAdmin(BaseModelAdmin):  
    10741075            # something is screwed up with the database, so display an error
    10751076            # page.
    10761077            if ERROR_FLAG in request.GET.keys():
    1077                 return render_to_response('admin/invalid_setup.html', {'title': _('Database error')})
     1078                return SimpleTemplateResponse('admin/invalid_setup.html', context={'title': _('Database error')})
    10781079            return HttpResponseRedirect(request.path + '?' + ERROR_FLAG + '=1')
    10791080
    10801081        # If the request was POSTed, this might be a bulk action or a bulk
    class ModelAdmin(BaseModelAdmin):  
    11831184            'actions_selection_counter': self.actions_selection_counter,
    11841185        }
    11851186        context.update(extra_context or {})
    1186         context_instance = template.RequestContext(request, current_app=self.admin_site.name)
    1187         return render_to_response(self.change_list_template or [
     1187
     1188        return TemplateResponse(request, self.change_list_template or [
    11881189            'admin/%s/%s/change_list.html' % (app_label, opts.object_name.lower()),
    11891190            'admin/%s/change_list.html' % app_label,
    11901191            'admin/change_list.html'
    1191         ], context, context_instance=context_instance)
     1192        ], context=context, current_app=self.admin_site.name)
    11921193
    11931194    @csrf_protect_m
    11941195    @transaction.commit_on_success
    class ModelAdmin(BaseModelAdmin):  
    12441245            "app_label": app_label,
    12451246        }
    12461247        context.update(extra_context or {})
    1247         context_instance = template.RequestContext(request, current_app=self.admin_site.name)
    1248         return render_to_response(self.delete_confirmation_template or [
     1248
     1249        return TemplateResponse(request, self.delete_confirmation_template or [
    12491250            "admin/%s/%s/delete_confirmation.html" % (app_label, opts.object_name.lower()),
    12501251            "admin/%s/delete_confirmation.html" % app_label,
    12511252            "admin/delete_confirmation.html"
    1252         ], context, context_instance=context_instance)
     1253        ], context=context, current_app=self.admin_site.name)
    12531254
    12541255    def history_view(self, request, object_id, extra_context=None):
    12551256        "The 'history' admin view for this model."
    class ModelAdmin(BaseModelAdmin):  
    12721273            'app_label': app_label,
    12731274        }
    12741275        context.update(extra_context or {})
    1275         context_instance = template.RequestContext(request, current_app=self.admin_site.name)
    1276         return render_to_response(self.object_history_template or [
     1276        return TemplateResponse(request, self.object_history_template or [
    12771277            "admin/%s/%s/object_history.html" % (app_label, opts.object_name.lower()),
    12781278            "admin/%s/object_history.html" % app_label,
    12791279            "admin/object_history.html"
    1280         ], context, context_instance=context_instance)
     1280        ], context=context, current_app=self.admin_site.name)
    12811281
    12821282class InlineModelAdmin(BaseModelAdmin):
    12831283    """
  • django/contrib/admin/sites.py

    diff --git a/django/contrib/admin/sites.py b/django/contrib/admin/sites.py
    index 1f98db8..0485cdd 100644
    a b from django.views.decorators.csrf import csrf_protect  
    99from django.db.models.base import ModelBase
    1010from django.core.exceptions import ImproperlyConfigured
    1111from django.core.urlresolvers import reverse
    12 from django.shortcuts import render_to_response
     12from django.template.response import TemplateResponse
     13from django.utils.functional import update_wrapper
    1314from django.utils.safestring import mark_safe
    1415from django.utils.text import capfirst
    1516from django.utils.translation import ugettext as _
    class AdminSite(object):  
    377378            'root_path': self.root_path,
    378379        }
    379380        context.update(extra_context or {})
    380         context_instance = template.RequestContext(request, current_app=self.name)
    381         return render_to_response(self.index_template or 'admin/index.html', context,
    382             context_instance=context_instance
    383         )
     381
     382        return TemplateResponse(request,
     383                                self.index_template or 'admin/index.html',
     384                                context=context,
     385                                current_app=self.name)
    384386
    385387    def app_index(self, request, app_label, extra_context=None):
    386388        user = request.user
    class AdminSite(object):  
    421423            'root_path': self.root_path,
    422424        }
    423425        context.update(extra_context or {})
    424         context_instance = template.RequestContext(request, current_app=self.name)
    425         return render_to_response(self.app_index_template or ('admin/%s/app_index.html' % app_label,
    426             'admin/app_index.html'), context,
    427             context_instance=context_instance
     426
     427        return TemplateResponse(request,
     428            self.app_index_template or ('admin/%s/app_index.html' % app_label, 'admin/app_index.html'),
     429            context=context, current_app=self.name
    428430        )
    429431
    430432# This global object represents the default admin site, for the common case.
  • django/contrib/admin/views/decorators.py

    diff --git a/django/contrib/admin/views/decorators.py b/django/contrib/admin/views/decorators.py
    index 9fabe64..686864c 100644
    a b  
    11from functools import wraps
     2
     3from django import template
    24from django.utils.translation import ugettext as _
    35from django.contrib.admin.forms import AdminAuthenticationForm
    46from django.contrib.auth.views import login
  • django/contrib/auth/admin.py

    diff --git a/django/contrib/auth/admin.py b/django/contrib/auth/admin.py
    index 8cd57f5..2d1738c 100644
    a b from django.contrib.auth.models import User, Group  
    66from django.contrib import messages
    77from django.core.exceptions import PermissionDenied
    88from django.http import HttpResponseRedirect, Http404
    9 from django.shortcuts import render_to_response, get_object_or_404
    10 from django.template import RequestContext
     9from django.shortcuts import get_object_or_404
     10from django.template.response import TemplateResponse
    1111from django.utils.html import escape
    1212from django.utils.decorators import method_decorator
    1313from django.utils.translation import ugettext, ugettext_lazy as _
    class UserAdmin(admin.ModelAdmin):  
    119119        fieldsets = [(None, {'fields': form.base_fields.keys()})]
    120120        adminForm = admin.helpers.AdminForm(form, fieldsets, {})
    121121
    122         return render_to_response(self.change_user_password_template or 'admin/auth/user/change_password.html', {
     122        return TemplateResponse(request, self.change_user_password_template or 'admin/auth/user/change_password.html', {
    123123            'title': _('Change password: %s') % escape(user.username),
    124124            'adminForm': adminForm,
    125125            'form': form,
    class UserAdmin(admin.ModelAdmin):  
    134134            'save_as': False,
    135135            'show_save': True,
    136136            'root_path': self.admin_site.root_path,
    137         }, context_instance=RequestContext(request))
     137        })
    138138
    139139    def response_add(self, request, obj, post_url_continue='../%s/'):
    140140        """
  • django/contrib/auth/views.py

    diff --git a/django/contrib/auth/views.py b/django/contrib/auth/views.py
    index eba83a2..1389fbd 100644
    a b import urlparse  
    33from django.conf import settings
    44from django.core.urlresolvers import reverse
    55from django.http import HttpResponseRedirect, QueryDict
    6 from django.shortcuts import render_to_response
    7 from django.template import RequestContext
     6from django.template.response import TemplateResponse
    87from django.utils.http import base36_to_int
    98from django.utils.translation import ugettext as _
    109from django.views.decorators.cache import never_cache
    def login(request, template_name='registration/login.html',  
    3938            if not redirect_to:
    4039                redirect_to = settings.LOGIN_REDIRECT_URL
    4140
    42             # Security check -- don't allow redirection to a different
     41            # Heavier security check -- don't allow redirection to a different
    4342            # host.
    4443            elif netloc and netloc != request.get_host():
    4544                redirect_to = settings.LOGIN_REDIRECT_URL
    def login(request, template_name='registration/login.html',  
    6463        'site': current_site,
    6564        'site_name': current_site.name,
    6665    }
    67     context.update(extra_context or {})
    68     return render_to_response(template_name, context,
    69                               context_instance=RequestContext(request, current_app=current_app))
     66
     67    if extra_context is not None:
     68        context.update(extra_context)
     69
     70    return TemplateResponse(request, template_name, context=context,
     71                            current_app=current_app)
    7072
    7173def logout(request, next_page=None,
    7274           template_name='registration/logged_out.html',
    def logout(request, next_page=None,  
    9092            'site_name': current_site.name,
    9193            'title': _('Logged out')
    9294        }
    93         context.update(extra_context or {})
    94         return render_to_response(template_name, context,
    95                                   context_instance=RequestContext(request, current_app=current_app))
     95
     96        if extra_context is not None:
     97            context.update(extra_context)
     98
     99        return TemplateResponse(request, template_name, context=context,
     100                                current_app=current_app)
    96101    else:
    97102        # Redirect to this page until the session has been cleared.
    98103        return HttpResponseRedirect(next_page or request.path)
    def password_reset(request, is_admin_site=False,  
    156161            return HttpResponseRedirect(post_reset_redirect)
    157162    else:
    158163        form = password_reset_form()
     164
    159165    context = {
    160166        'form': form,
    161167    }
    162     context.update(extra_context or {})
    163     return render_to_response(template_name, context,
    164                               context_instance=RequestContext(request, current_app=current_app))
     168    if extra_context is not None:
     169        context.update(extra_context)
     170
     171    return TemplateResponse(request, template_name, context=context,
     172                            current_app=current_app)
    165173
    166174def password_reset_done(request,
    167175                        template_name='registration/password_reset_done.html',
    168176                        current_app=None, extra_context=None):
     177
    169178    context = {}
    170     context.update(extra_context or {})
    171     return render_to_response(template_name, context,
    172                               context_instance=RequestContext(request, current_app=current_app))
     179
     180    if extra_context is not None:
     181        context.update(extra_context)
     182
     183    return TemplateResponse(request, template_name, context=context,
     184                            current_app=current_app)
    173185
    174186# Doesn't need csrf_protect since no-one can guess the URL
    175187@never_cache
    def password_reset_confirm(request, uidb36=None, token=None,  
    208220        'form': form,
    209221        'validlink': validlink,
    210222    }
    211     context.update(extra_context or {})
    212     return render_to_response(template_name, context,
    213                               context_instance=RequestContext(request, current_app=current_app))
     223
     224    if extra_context is not None:
     225        context.update(extra_context)
     226
     227    return TemplateResponse(request, template_name, context=context,
     228                            current_app=current_app)
    214229
    215230def password_reset_complete(request,
    216231                            template_name='registration/password_reset_complete.html',
    def password_reset_complete(request,  
    218233    context = {
    219234        'login_url': settings.LOGIN_URL
    220235    }
    221     context.update(extra_context or {})
    222     return render_to_response(template_name, context,
    223                               context_instance=RequestContext(request, current_app=current_app))
     236
     237    if extra_context is not None:
     238        context.update(extra_context)
     239
     240    return TemplateResponse(request, template_name, context=context,
     241                            current_app=current_app)
    224242
    225243@csrf_protect
    226244@login_required
    def password_change(request,  
    241259    context = {
    242260        'form': form,
    243261    }
    244     context.update(extra_context or {})
    245     return render_to_response(template_name, context,
    246                               context_instance=RequestContext(request, current_app=current_app))
     262
     263    if extra_context is not None:
     264        context.update(extra_context)
     265
     266    return TemplateResponse(request, template_name, context=context,
     267                            current_app=current_app)
    247268
    248269def password_change_done(request,
    249270                         template_name='registration/password_change_done.html',
    250271                         current_app=None, extra_context=None):
     272
    251273    context = {}
    252     context.update(extra_context or {})
    253     return render_to_response(template_name, context,
    254                               context_instance=RequestContext(request, current_app=current_app))
     274
     275    if extra_context is not None:
     276        context.update(extra_context)
     277
     278    return TemplateResponse(request, template_name, context=context,
     279                            current_app=current_app)
  • docs/ref/contrib/admin/index.txt

    diff --git a/docs/ref/contrib/admin/index.txt b/docs/ref/contrib/admin/index.txt
    index f97d4eb..633c53f 100644
    a b provided some extra mapping data that would not otherwise be available::  
    10641064            return super(MyModelAdmin, self).change_view(request, object_id,
    10651065                extra_context=my_context)
    10661066
     1067.. versionadded:: 1.4
     1068
     1069These views now return :class:`~django.template.response.TemplateResponse`
     1070instances which allow you to easily customize the response data before
     1071rendering. For more details, see the
     1072:doc:`TemplateResponse documentation </ref/template-response>`.
     1073
    10671074``ModelAdmin`` media definitions
    10681075--------------------------------
    10691076
  • tests/regressiontests/admin_views/tests.py

    diff --git a/tests/regressiontests/admin_views/tests.py b/tests/regressiontests/admin_views/tests.py
    index 9b1a738..0537160 100644
    a b from django.contrib.admin.helpers import ACTION_CHECKBOX_NAME  
    2020from django.contrib.admin.views.main import IS_POPUP_VAR
    2121from django.forms.util import ErrorList
    2222import django.template.context
     23from django.template.response import TemplateResponse
    2324from django.test import TestCase
    2425from django.utils import formats
    2526from django.utils.cache import get_max_age
    class AdminViewBasicTest(TestCase):  
    7677        A smoke test to ensure GET on the add_view works.
    7778        """
    7879        response = self.client.get('/test_admin/%s/admin_views/section/add/' % self.urlbit)
     80        self.assertIsInstance(response, TemplateResponse)
    7981        self.assertEqual(response.status_code, 200)
    8082
    8183    def testAddWithGETArgs(self):
    class AdminViewBasicTest(TestCase):  
    9193        A smoke test to ensure GET on the change_view works.
    9294        """
    9395        response = self.client.get('/test_admin/%s/admin_views/section/1/' % self.urlbit)
     96        self.assertIsInstance(response, TemplateResponse)
    9497        self.assertEqual(response.status_code, 200)
    9598
    9699    def testBasicEditGetStringPK(self):
    class CustomModelAdminTest(AdminViewBasicTest):  
    488491
    489492    def testCustomAdminSiteLoginForm(self):
    490493        self.client.logout()
    491         request = self.client.get('/test_admin/admin2/')
    492         self.assertEqual(request.status_code, 200)
     494        response = self.client.get('/test_admin/admin2/')
     495        self.assertIsInstance(response, TemplateResponse)
     496        self.assertEqual(response.status_code, 200)
    493497        login = self.client.post('/test_admin/admin2/', {
    494498            REDIRECT_FIELD_NAME: '/test_admin/admin2/',
    495499            LOGIN_FORM_KEY: 1,
    496500            'username': 'customform',
    497501            'password': 'secret',
    498502        })
     503        self.assertIsInstance(login, TemplateResponse)
    499504        self.assertEqual(login.status_code, 200)
    500505        self.assertContains(login, 'custom form error')
    501506
    502507    def testCustomAdminSiteLoginTemplate(self):
    503508        self.client.logout()
    504509        request = self.client.get('/test_admin/admin2/')
     510        self.assertIsInstance(request, TemplateResponse)
    505511        self.assertTemplateUsed(request, 'custom_admin/login.html')
    506512        self.assertTrue('Hello from a custom login template' in request.content)
    507513
    508514    def testCustomAdminSiteLogoutTemplate(self):
    509515        request = self.client.get('/test_admin/admin2/logout/')
     516        self.assertIsInstance(request, TemplateResponse)
    510517        self.assertTemplateUsed(request, 'custom_admin/logout.html')
    511518        self.assertTrue('Hello from a custom logout template' in request.content)
    512519
    513520    def testCustomAdminSiteIndexViewAndTemplate(self):
    514521        request = self.client.get('/test_admin/admin2/')
     522        self.assertIsInstance(request, TemplateResponse)
    515523        self.assertTemplateUsed(request, 'custom_admin/index.html')
    516524        self.assertTrue('Hello from a custom index template *bar*' in request.content)
    517525
    518526    def testCustomAdminSitePasswordChangeTemplate(self):
    519527        request = self.client.get('/test_admin/admin2/password_change/')
     528        self.assertIsInstance(request, TemplateResponse)
    520529        self.assertTemplateUsed(request, 'custom_admin/password_change_form.html')
    521530        self.assertTrue('Hello from a custom password change form template' in request.content)
    522531
    523532    def testCustomAdminSitePasswordChangeDoneTemplate(self):
    524533        request = self.client.get('/test_admin/admin2/password_change/done/')
     534        self.assertIsInstance(request, TemplateResponse)
    525535        self.assertTemplateUsed(request, 'custom_admin/password_change_done.html')
    526536        self.assertTrue('Hello from a custom password change done template' in request.content)
    527537
    class AdminViewPermissionsTest(TestCase):  
    631641        self.assertFalse(login.context)
    632642        self.client.get('/test_admin/admin/logout/')
    633643
    634         # Test if user enters email address
     644        # Test if user enters e-mail address
    635645        request = self.client.get('/test_admin/admin/')
    636646        self.assertEqual(request.status_code, 200)
    637647        login = self.client.post('/test_admin/admin/', self.super_email_login)
    class AdminViewPermissionsTest(TestCase):  
    641651        self.assertContains(login, "Please enter a correct username and password.")
    642652        new_user = User(username='jondoe', password='secret', email='super@example.com')
    643653        new_user.save()
    644         # check to ensure if there are multiple email addresses a user doesn't get a 500
     654        # check to ensure if there are multiple e-mail addresses a user doesn't get a 500
    645655        login = self.client.post('/test_admin/admin/', self.super_email_login)
    646656        self.assertContains(login, "Please enter a correct username and password.")
    647657
    class SecureViewTests(TestCase):  
    12271237        # make sure the view removes test cookie
    12281238        self.assertEqual(self.client.session.test_cookie_worked(), False)
    12291239
    1230         # Test if user enters email address
     1240        # Test if user enters e-mail address
    12311241        request = self.client.get('/test_admin/admin/secure-view/')
    12321242        self.assertEqual(request.status_code, 200)
    12331243        login = self.client.post('/test_admin/admin/secure-view/', self.super_email_login)
    class SecureViewTests(TestCase):  
    12371247        self.assertContains(login, "Please enter a correct username and password.")
    12381248        new_user = User(username='jondoe', password='secret', email='super@example.com')
    12391249        new_user.save()
    1240         # check to ensure if there are multiple email addresses a user doesn't get a 500
     1250        # check to ensure if there are multiple e-mail addresses a user doesn't get a 500
    12411251        login = self.client.post('/test_admin/admin/secure-view/', self.super_email_login)
    12421252        self.assertContains(login, "Please enter a correct username and password.")
    12431253
    class AdminActionsTest(TestCase):  
    18741884            'post': 'yes',
    18751885        }
    18761886        confirmation = self.client.post('/test_admin/admin/admin_views/subscriber/', action_data)
    1877         self.assertContains(confirmation, "Are you sure you want to delete the selected subscribers")
     1887        self.assertIsInstance(confirmation, TemplateResponse)
     1888        self.assertContains(confirmation, "Are you sure you want to delete the selected subscribers?")
    18781889        self.assertTrue(confirmation.content.count(ACTION_CHECKBOX_NAME) == 2)
    18791890        response = self.client.post('/test_admin/admin/admin_views/subscriber/', delete_confirmation_data)
    18801891        self.assertEqual(Subscriber.objects.count(), 0)
Back to Top