Fixed #12226 -- Deprecated test client Response.template attribute in favor of templates attribute, which is always a list. Thanks Russell for patch review.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@14106 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
d084439c41
commit
501546df6f
|
@ -4,6 +4,7 @@ import sys
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import mimetypes
|
import mimetypes
|
||||||
|
import warnings
|
||||||
try:
|
try:
|
||||||
from cStringIO import StringIO
|
from cStringIO import StringIO
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
@ -93,7 +94,7 @@ def store_rendered_templates(store, signal, sender, template, context, **kwargs)
|
||||||
"""
|
"""
|
||||||
Stores templates and contexts that are rendered.
|
Stores templates and contexts that are rendered.
|
||||||
"""
|
"""
|
||||||
store.setdefault('template', []).append(template)
|
store.setdefault('templates', []).append(template)
|
||||||
store.setdefault('context', ContextList()).append(context)
|
store.setdefault('context', ContextList()).append(context)
|
||||||
|
|
||||||
def encode_multipart(boundary, data):
|
def encode_multipart(boundary, data):
|
||||||
|
@ -260,16 +261,25 @@ class Client(object):
|
||||||
response.request = request
|
response.request = request
|
||||||
|
|
||||||
# Add any rendered template detail to the response.
|
# Add any rendered template detail to the response.
|
||||||
# If there was only one template rendered (the most likely case),
|
response.templates = data.get("templates", [])
|
||||||
# flatten the list to a single element.
|
response.context = data.get("context")
|
||||||
for detail in ('template', 'context'):
|
|
||||||
if data.get(detail):
|
# Flatten a single context. Not really necessary anymore thanks to
|
||||||
if len(data[detail]) == 1:
|
# the __getattr__ flattening in ContextList, but has some edge-case
|
||||||
setattr(response, detail, data[detail][0]);
|
# backwards-compatibility implications.
|
||||||
else:
|
if response.context and len(response.context) == 1:
|
||||||
setattr(response, detail, data[detail])
|
response.context = response.context[0]
|
||||||
else:
|
|
||||||
setattr(response, detail, None)
|
# Provide a backwards-compatible (but pending deprecation) response.template
|
||||||
|
def _get_template(self):
|
||||||
|
warnings.warn("response.template is deprecated; use response.templates instead (which is always a list)",
|
||||||
|
PendingDeprecationWarning)
|
||||||
|
if not self.templates:
|
||||||
|
return None
|
||||||
|
elif len(self.templates) == 1:
|
||||||
|
return self.templates[0]
|
||||||
|
return self.templates
|
||||||
|
response.__class__.template = property(_get_template)
|
||||||
|
|
||||||
# Update persistent cookie data.
|
# Update persistent cookie data.
|
||||||
if response.cookies:
|
if response.cookies:
|
||||||
|
|
|
@ -443,7 +443,7 @@ class TransactionTestCase(unittest.TestCase):
|
||||||
if msg_prefix:
|
if msg_prefix:
|
||||||
msg_prefix += ": "
|
msg_prefix += ": "
|
||||||
|
|
||||||
template_names = [t.name for t in to_list(response.template)]
|
template_names = [t.name for t in response.templates]
|
||||||
if not template_names:
|
if not template_names:
|
||||||
self.fail(msg_prefix + "No templates used to render the response")
|
self.fail(msg_prefix + "No templates used to render the response")
|
||||||
self.failUnless(template_name in template_names,
|
self.failUnless(template_name in template_names,
|
||||||
|
@ -459,7 +459,7 @@ class TransactionTestCase(unittest.TestCase):
|
||||||
if msg_prefix:
|
if msg_prefix:
|
||||||
msg_prefix += ": "
|
msg_prefix += ": "
|
||||||
|
|
||||||
template_names = [t.name for t in to_list(response.template)]
|
template_names = [t.name for t in response.templates]
|
||||||
self.failIf(template_name in template_names,
|
self.failIf(template_name in template_names,
|
||||||
msg_prefix + "Template '%s' was used unexpectedly in rendering"
|
msg_prefix + "Template '%s' was used unexpectedly in rendering"
|
||||||
" the response" % template_name)
|
" the response" % template_name)
|
||||||
|
|
|
@ -102,6 +102,12 @@ their deprecation, as per the :ref:`Django deprecation policy
|
||||||
* The ``mod_python`` request handler has been deprecated since the 1.3
|
* The ``mod_python`` request handler has been deprecated since the 1.3
|
||||||
release. The ``mod_wsgi`` handler should be used instead.
|
release. The ``mod_wsgi`` handler should be used instead.
|
||||||
|
|
||||||
|
* The ``template`` attribute on :class:`~django.test.client.Response`
|
||||||
|
objects returned by the :ref:`test client <test-client>` has been
|
||||||
|
deprecated since the 1.3 release. The
|
||||||
|
:attr:`~django.test.client.Response.templates` attribute should be
|
||||||
|
used instead.
|
||||||
|
|
||||||
* 2.0
|
* 2.0
|
||||||
* ``django.views.defaults.shortcut()``. This function has been moved
|
* ``django.views.defaults.shortcut()``. This function has been moved
|
||||||
to ``django.contrib.contenttypes.views.shortcut()`` as part of the
|
to ``django.contrib.contenttypes.views.shortcut()`` as part of the
|
||||||
|
|
|
@ -106,6 +106,23 @@ If you are currently using the ``mod_python`` request handler, it is strongly
|
||||||
encouraged you redeploy your Django instances using :doc:`mod_wsgi
|
encouraged you redeploy your Django instances using :doc:`mod_wsgi
|
||||||
</howto/deployment/modwsgi>`.
|
</howto/deployment/modwsgi>`.
|
||||||
|
|
||||||
|
Test client response ``template`` attribute
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Django's :ref:`test client <test-client>` returns
|
||||||
|
:class:`~django.test.client.Response` objects annotated with extra testing
|
||||||
|
information. In Django versions prior to 1.3, this included a
|
||||||
|
:attr:`~django.test.client.Response.template` attribute containing information
|
||||||
|
about templates rendered in generating the response: either None, a single
|
||||||
|
:class:`~django.template.Template` object, or a list of
|
||||||
|
:class:`~django.template.Template` objects. This inconsistency in return values
|
||||||
|
(sometimes a list, sometimes not) made the attribute difficult to work with.
|
||||||
|
|
||||||
|
In Django 1.3 the :attr:`~django.test.client.Response.template` attribute is
|
||||||
|
deprecated in favor of a new :attr:`~django.test.client.Response.templates`
|
||||||
|
attribute, which is always a list, even if it has only a single element or no
|
||||||
|
elements.
|
||||||
|
|
||||||
What's new in Django 1.3
|
What's new in Django 1.3
|
||||||
========================
|
========================
|
||||||
|
|
||||||
|
|
|
@ -494,6 +494,8 @@ Testing tools
|
||||||
|
|
||||||
Django provides a small set of tools that come in handy when writing tests.
|
Django provides a small set of tools that come in handy when writing tests.
|
||||||
|
|
||||||
|
.. _test-client:
|
||||||
|
|
||||||
The test client
|
The test client
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
@ -894,15 +896,15 @@ Specifically, a ``Response`` object has the following attributes:
|
||||||
The HTTP status of the response, as an integer. See RFC2616_ for a full
|
The HTTP status of the response, as an integer. See RFC2616_ for a full
|
||||||
list of HTTP status codes.
|
list of HTTP status codes.
|
||||||
|
|
||||||
.. attribute:: template
|
.. versionadded:: 1.3
|
||||||
|
|
||||||
The ``Template`` instance that was used to render the final content. Use
|
.. attribute:: templates
|
||||||
|
|
||||||
|
A list of ``Template`` instances used to render the final content, in
|
||||||
|
the order they were rendered. For each template in the list, use
|
||||||
``template.name`` to get the template's file name, if the template was
|
``template.name`` to get the template's file name, if the template was
|
||||||
loaded from a file. (The name is a string such as ``'admin/index.html'``.)
|
loaded from a file. (The name is a string such as
|
||||||
|
``'admin/index.html'``.)
|
||||||
If the rendered page used multiple templates -- e.g., using :ref:`template
|
|
||||||
inheritance<template-inheritance>` -- then ``template`` will be a list of
|
|
||||||
``Template`` instances, in the order in which they were rendered.
|
|
||||||
|
|
||||||
You can also use dictionary syntax on the response object to query the value
|
You can also use dictionary syntax on the response object to query the value
|
||||||
of any settings in the HTTP headers. For example, you could determine the
|
of any settings in the HTTP headers. For example, you could determine the
|
||||||
|
|
|
@ -37,7 +37,7 @@ class ClientTest(TestCase):
|
||||||
# Check some response details
|
# Check some response details
|
||||||
self.assertContains(response, 'This is a test')
|
self.assertContains(response, 'This is a test')
|
||||||
self.assertEqual(response.context['var'], u'\xf2')
|
self.assertEqual(response.context['var'], u'\xf2')
|
||||||
self.assertEqual(response.template.name, 'GET Template')
|
self.assertEqual(response.templates[0].name, 'GET Template')
|
||||||
|
|
||||||
def test_get_post_view(self):
|
def test_get_post_view(self):
|
||||||
"GET a view that normally expects POSTs"
|
"GET a view that normally expects POSTs"
|
||||||
|
@ -45,7 +45,7 @@ class ClientTest(TestCase):
|
||||||
|
|
||||||
# Check some response details
|
# Check some response details
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertEqual(response.template.name, 'Empty GET Template')
|
self.assertEqual(response.templates[0].name, 'Empty GET Template')
|
||||||
self.assertTemplateUsed(response, 'Empty GET Template')
|
self.assertTemplateUsed(response, 'Empty GET Template')
|
||||||
self.assertTemplateNotUsed(response, 'Empty POST Template')
|
self.assertTemplateNotUsed(response, 'Empty POST Template')
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ class ClientTest(TestCase):
|
||||||
|
|
||||||
# Check some response details
|
# Check some response details
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertEqual(response.template.name, 'Empty POST Template')
|
self.assertEqual(response.templates[0].name, 'Empty POST Template')
|
||||||
self.assertTemplateNotUsed(response, 'Empty GET Template')
|
self.assertTemplateNotUsed(response, 'Empty GET Template')
|
||||||
self.assertTemplateUsed(response, 'Empty POST Template')
|
self.assertTemplateUsed(response, 'Empty POST Template')
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ class ClientTest(TestCase):
|
||||||
# Check some response details
|
# Check some response details
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertEqual(response.context['data'], '37')
|
self.assertEqual(response.context['data'], '37')
|
||||||
self.assertEqual(response.template.name, 'POST Template')
|
self.assertEqual(response.templates[0].name, 'POST Template')
|
||||||
self.failUnless('Data received' in response.content)
|
self.failUnless('Data received' in response.content)
|
||||||
|
|
||||||
def test_response_headers(self):
|
def test_response_headers(self):
|
||||||
|
@ -84,7 +84,7 @@ class ClientTest(TestCase):
|
||||||
response = self.client.post("/test_client/raw_post_view/", test_doc,
|
response = self.client.post("/test_client/raw_post_view/", test_doc,
|
||||||
content_type="text/xml")
|
content_type="text/xml")
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertEqual(response.template.name, "Book template")
|
self.assertEqual(response.templates[0].name, "Book template")
|
||||||
self.assertEqual(response.content, "Blink - Malcolm Gladwell")
|
self.assertEqual(response.content, "Blink - Malcolm Gladwell")
|
||||||
|
|
||||||
def test_redirect(self):
|
def test_redirect(self):
|
||||||
|
|
|
@ -9,7 +9,7 @@ from django.test import Client, TestCase
|
||||||
from django.test.utils import ContextList
|
from django.test.utils import ContextList
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.core.exceptions import SuspiciousOperation
|
from django.core.exceptions import SuspiciousOperation
|
||||||
from django.template import TemplateDoesNotExist, TemplateSyntaxError, Context
|
from django.template import TemplateDoesNotExist, TemplateSyntaxError, Context, Template
|
||||||
from django.template import loader
|
from django.template import loader
|
||||||
from django.test.client import encode_file
|
from django.test.client import encode_file
|
||||||
|
|
||||||
|
@ -861,3 +861,18 @@ class RequestHeadersTest(TestCase):
|
||||||
self.assertEquals(response.content, "HTTP_X_ARG_CHECK: Testing 123")
|
self.assertEquals(response.content, "HTTP_X_ARG_CHECK: Testing 123")
|
||||||
self.assertRedirects(response, '/test_client_regress/check_headers/',
|
self.assertRedirects(response, '/test_client_regress/check_headers/',
|
||||||
status_code=301, target_status_code=200)
|
status_code=301, target_status_code=200)
|
||||||
|
|
||||||
|
class ResponseTemplateDeprecationTests(TestCase):
|
||||||
|
"""
|
||||||
|
Response.template still works backwards-compatibly, but with pending deprecation warning. Refs #12226.
|
||||||
|
|
||||||
|
"""
|
||||||
|
def test_response_template_data(self):
|
||||||
|
response = self.client.get("/test_client_regress/request_data/", data={'foo':'whiz'})
|
||||||
|
self.assertEqual(response.template.__class__, Template)
|
||||||
|
self.assertEqual(response.template.name, 'base.html')
|
||||||
|
|
||||||
|
def test_response_no_template(self):
|
||||||
|
response = self.client.get("/test_client_regress/request_methods/")
|
||||||
|
self.assertEqual(response.template, None)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue