Fixed #10482 -- Unified access to response.context when inspecting responses from the test client. Thanks to James Bennett for the design, and Julien Phalip for the patch.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@10084 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Russell Keith-Magee 2009-03-18 10:46:55 +00:00
parent 61a2708c41
commit ee2f04d79e
7 changed files with 58 additions and 5 deletions

View File

@ -20,6 +20,7 @@ from django.utils.encoding import smart_str
from django.utils.http import urlencode
from django.utils.itercompat import is_iterable
from django.db import transaction, close_connection
from django.test.utils import ContextList
BOUNDARY = 'BoUnDaRyStRiNg'
MULTIPART_CONTENT = 'multipart/form-data; boundary=%s' % BOUNDARY
@ -80,8 +81,8 @@ def store_rendered_templates(store, signal, sender, template, context, **kwargs)
"""
Stores templates and contexts that are rendered.
"""
store.setdefault('template',[]).append(template)
store.setdefault('context',[]).append(context)
store.setdefault('template', []).append(template)
store.setdefault('context', ContextList()).append(context)
def encode_multipart(boundary, data):
"""

View File

@ -6,6 +6,20 @@ from django.test import signals
from django.template import Template
from django.utils.translation import deactivate
class ContextList(list):
"""A wrapper that provides direct key access to context items contained
in a list of context objects.
"""
def __getitem__(self, key):
if isinstance(key, basestring):
for subcontext in self:
if key in subcontext:
return subcontext[key]
raise KeyError
else:
return super(ContextList, self).__getitem__(key)
def instrumented_test_render(self, context):
"""
An instrumented Template render method, providing a signal

View File

@ -712,6 +712,16 @@ Specifically, a ``Response`` object has the following attributes:
If the rendered page used multiple templates, then ``context`` will be a
list of ``Context`` objects, in the order in which they were rendered.
.. versionadded:: 1.1
Regardless of the number of templates used during rendering, you can
retrieve context values using the ``[]`` operator. For example, the
context variable ``name`` could be retrieved using::
>>> response = client.get('/foo/')
>>> response.context['name']
'Arthur'
.. attribute:: request
The request data that stimulated the response.

View File

@ -5,9 +5,10 @@ import os
from django.conf import settings
from django.test import Client, TestCase
from django.test.utils import ContextList
from django.core.urlresolvers import reverse
from django.core.exceptions import SuspiciousOperation
from django.template import TemplateDoesNotExist, TemplateSyntaxError
from django.template import TemplateDoesNotExist, TemplateSyntaxError, Context
class AssertContainsTests(TestCase):
def test_contains(self):
@ -455,6 +456,26 @@ class zzUrlconfSubstitutionTests(TestCase):
url = reverse('arg_view', args=['somename'])
self.assertEquals(url, '/test_client_regress/arg_view/somename/')
class ContextTests(TestCase):
fixtures = ['testdata']
def test_single_context(self):
"Context variables can be retrieved from a single context"
response = self.client.get("/test_client_regress/request_data/", data={'foo':'whiz'})
self.assertEqual(response.context.__class__, Context)
self.assertEqual(response.context['get-foo'], 'whiz')
self.assertEqual(response.context['request-foo'], 'whiz')
self.assertEqual(response.context['data'], 'sausage')
def test_inherited_context(self):
"Context variables can be retrieved from a list of contexts"
response = self.client.get("/test_client_regress/request_data_extended/", data={'foo':'whiz'})
self.assertEqual(response.context.__class__, ContextList)
self.assertEqual(len(response.context), 2)
self.assertEqual(response.context['get-foo'], 'whiz')
self.assertEqual(response.context['request-foo'], 'whiz')
self.assertEqual(response.context['data'], 'bacon')
class SessionTests(TestCase):
fixtures = ['testdata.json']

View File

@ -7,6 +7,7 @@ urlpatterns = patterns('',
(r'^staff_only/$', views.staff_only_view),
(r'^get_view/$', views.get_view),
(r'^request_data/$', views.request_data),
(r'^request_data_extended/$', views.request_data, {'template':'extended.html', 'data':'bacon'}),
url(r'^arg_view/(?P<name>.+)/$', views.view_with_argument, name='arg_view'),
(r'^login_protected_redirect_view/$', views.login_protected_redirect_view),
(r'^redirects/$', redirect_to, {'url': '/test_client_regress/redirects/further/'}),

View File

@ -19,15 +19,16 @@ def get_view(request):
return HttpResponse("Hello world")
get_view = login_required(get_view)
def request_data(request):
def request_data(request, template='base.html', data='sausage'):
"A simple view that returns the request data in the context"
return render_to_response('base.html', {
return render_to_response(template, {
'get-foo':request.GET.get('foo',None),
'get-bar':request.GET.get('bar',None),
'post-foo':request.POST.get('foo',None),
'post-bar':request.POST.get('bar',None),
'request-foo':request.REQUEST.get('foo',None),
'request-bar':request.REQUEST.get('bar',None),
'data': data,
})
def view_with_argument(request, name):

View File

@ -0,0 +1,5 @@
{% extends "base.html" %}
{% block title %}Extended template{% endblock %}
{% block content %}
This is just a template extending the base.
{% endblock %}