Fixed #12816 -- Added a render() shortcut.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@15008 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
d4ef841495
commit
b3d2091681
|
@ -4,7 +4,7 @@ of MVC. In other words, these functions/classes introduce controlled coupling
|
||||||
for convenience's sake.
|
for convenience's sake.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from django.template import loader
|
from django.template import loader, RequestContext
|
||||||
from django.http import HttpResponse, Http404
|
from django.http import HttpResponse, Http404
|
||||||
from django.http import HttpResponseRedirect, HttpResponsePermanentRedirect
|
from django.http import HttpResponseRedirect, HttpResponsePermanentRedirect
|
||||||
from django.db.models.manager import Manager
|
from django.db.models.manager import Manager
|
||||||
|
@ -19,20 +19,31 @@ def render_to_response(*args, **kwargs):
|
||||||
httpresponse_kwargs = {'mimetype': kwargs.pop('mimetype', None)}
|
httpresponse_kwargs = {'mimetype': kwargs.pop('mimetype', None)}
|
||||||
return HttpResponse(loader.render_to_string(*args, **kwargs), **httpresponse_kwargs)
|
return HttpResponse(loader.render_to_string(*args, **kwargs), **httpresponse_kwargs)
|
||||||
|
|
||||||
|
def render(request, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Returns a HttpResponse whose content is filled with the result of calling
|
||||||
|
django.template.loader.render_to_string() with the passed arguments.
|
||||||
|
Uses a RequestContext by default.
|
||||||
|
"""
|
||||||
|
httpresponse_kwargs = {'mimetype': kwargs.pop('mimetype', None)}
|
||||||
|
kwargs['context_instance'] = kwargs.get('context_instance', RequestContext(request))
|
||||||
|
return HttpResponse(loader.render_to_string(*args, **kwargs),
|
||||||
|
**httpresponse_kwargs)
|
||||||
|
|
||||||
def redirect(to, *args, **kwargs):
|
def redirect(to, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
Returns an HttpResponseRedirect to the apropriate URL for the arguments
|
Returns an HttpResponseRedirect to the apropriate URL for the arguments
|
||||||
passed.
|
passed.
|
||||||
|
|
||||||
The arguments could be:
|
The arguments could be:
|
||||||
|
|
||||||
* A model: the model's `get_absolute_url()` function will be called.
|
* A model: the model's `get_absolute_url()` function will be called.
|
||||||
|
|
||||||
* A view name, possibly with arguments: `urlresolvers.reverse()` will
|
* A view name, possibly with arguments: `urlresolvers.reverse()` will
|
||||||
be used to reverse-resolve the name.
|
be used to reverse-resolve the name.
|
||||||
|
|
||||||
* A URL, which will be used as-is for the redirect location.
|
* A URL, which will be used as-is for the redirect location.
|
||||||
|
|
||||||
By default issues a temporary redirect; pass permanent=True to issue a
|
By default issues a temporary redirect; pass permanent=True to issue a
|
||||||
permanent redirect
|
permanent redirect
|
||||||
"""
|
"""
|
||||||
|
@ -40,11 +51,11 @@ def redirect(to, *args, **kwargs):
|
||||||
redirect_class = HttpResponsePermanentRedirect
|
redirect_class = HttpResponsePermanentRedirect
|
||||||
else:
|
else:
|
||||||
redirect_class = HttpResponseRedirect
|
redirect_class = HttpResponseRedirect
|
||||||
|
|
||||||
# If it's a model, use get_absolute_url()
|
# If it's a model, use get_absolute_url()
|
||||||
if hasattr(to, 'get_absolute_url'):
|
if hasattr(to, 'get_absolute_url'):
|
||||||
return redirect_class(to.get_absolute_url())
|
return redirect_class(to.get_absolute_url())
|
||||||
|
|
||||||
# Next try a reverse URL resolution.
|
# Next try a reverse URL resolution.
|
||||||
try:
|
try:
|
||||||
return redirect_class(urlresolvers.reverse(to, args=args, kwargs=kwargs))
|
return redirect_class(urlresolvers.reverse(to, args=args, kwargs=kwargs))
|
||||||
|
@ -55,7 +66,7 @@ def redirect(to, *args, **kwargs):
|
||||||
# If this doesn't "feel" like a URL, re-raise.
|
# If this doesn't "feel" like a URL, re-raise.
|
||||||
if '/' not in to and '.' not in to:
|
if '/' not in to and '.' not in to:
|
||||||
raise
|
raise
|
||||||
|
|
||||||
# Finally, fall back and assume it's a URL
|
# Finally, fall back and assume it's a URL
|
||||||
return redirect_class(to)
|
return redirect_class(to)
|
||||||
|
|
||||||
|
@ -101,4 +112,5 @@ def get_list_or_404(klass, *args, **kwargs):
|
||||||
obj_list = list(queryset.filter(*args, **kwargs))
|
obj_list = list(queryset.filter(*args, **kwargs))
|
||||||
if not obj_list:
|
if not obj_list:
|
||||||
raise Http404('No %s matches the given query.' % queryset.model._meta.object_name)
|
raise Http404('No %s matches the given query.' % queryset.model._meta.object_name)
|
||||||
return obj_list
|
return obj_list
|
||||||
|
|
||||||
|
|
|
@ -215,6 +215,11 @@ requests. These include:
|
||||||
making it easier to write simple template tags that require
|
making it easier to write simple template tags that require
|
||||||
access to template context.
|
access to template context.
|
||||||
|
|
||||||
|
* A new :meth:`~django.shortcuts.render()` shortcut -- an
|
||||||
|
alternative to :meth:`~django.shortcuts.render_to_response()`
|
||||||
|
providing a :class:`~django.template.RequestContext` by
|
||||||
|
default.
|
||||||
|
|
||||||
.. _HTTPOnly: http://www.owasp.org/index.php/HTTPOnly
|
.. _HTTPOnly: http://www.owasp.org/index.php/HTTPOnly
|
||||||
|
|
||||||
.. _backwards-incompatible-changes-1.3:
|
.. _backwards-incompatible-changes-1.3:
|
||||||
|
|
|
@ -12,6 +12,70 @@ The package ``django.shortcuts`` collects helper functions and classes that
|
||||||
"span" multiple levels of MVC. In other words, these functions/classes
|
"span" multiple levels of MVC. In other words, these functions/classes
|
||||||
introduce controlled coupling for convenience's sake.
|
introduce controlled coupling for convenience's sake.
|
||||||
|
|
||||||
|
``render``
|
||||||
|
==========
|
||||||
|
|
||||||
|
.. function:: render(request, template[, dictionary][, context_instance][, mimetype])
|
||||||
|
|
||||||
|
Combines a given template with a given context dictionary and returns an
|
||||||
|
:class:`~django.http.HttpResponse` object with that rendered text.
|
||||||
|
|
||||||
|
:func:`render()` is the same as a call to
|
||||||
|
:func:`render_to_response()` with a context_instance argument that
|
||||||
|
that forces the use of a :class:`RequestContext`.
|
||||||
|
|
||||||
|
Required arguments
|
||||||
|
------------------
|
||||||
|
|
||||||
|
``request``
|
||||||
|
The request object used to generate this response.
|
||||||
|
|
||||||
|
``template``
|
||||||
|
The full name of a template to use or sequence of template names.
|
||||||
|
|
||||||
|
Optional arguments
|
||||||
|
------------------
|
||||||
|
|
||||||
|
``dictionary``
|
||||||
|
A dictionary of values to add to the template context. By default, this
|
||||||
|
is an empty dictionary. If a value in the dictionary is callable, the
|
||||||
|
view will call it just before rendering the template.
|
||||||
|
|
||||||
|
``context_instance``
|
||||||
|
The context instance to render the template with. By default, the template
|
||||||
|
will be rendered with a ``RequestContext`` instance (filled with values from
|
||||||
|
``request`` and ```dictionary``).
|
||||||
|
|
||||||
|
``mimetype``
|
||||||
|
The MIME type to use for the resulting document. Defaults to the value of
|
||||||
|
the :setting:`DEFAULT_CONTENT_TYPE` setting.
|
||||||
|
|
||||||
|
Example
|
||||||
|
-------
|
||||||
|
|
||||||
|
The following example renders the template ``myapp/index.html`` with the
|
||||||
|
MIME type ``application/xhtml+xml``::
|
||||||
|
|
||||||
|
from django.shortcuts import render_to_response
|
||||||
|
|
||||||
|
def my_view(request):
|
||||||
|
# View code here...
|
||||||
|
return render_to_response('myapp/index.html', {"foo": "bar"},
|
||||||
|
mimetype="application/xhtml+xml")
|
||||||
|
|
||||||
|
This example is equivalent to::
|
||||||
|
|
||||||
|
from django.http import HttpResponse
|
||||||
|
from django.template import Context, loader
|
||||||
|
|
||||||
|
def my_view(request):
|
||||||
|
# View code here...
|
||||||
|
t = loader.get_template('myapp/template.html')
|
||||||
|
c = RequestContext(request, {'foo': 'bar'})
|
||||||
|
return HttpResponse(t.render(c),
|
||||||
|
mimetype="application/xhtml+xml")
|
||||||
|
|
||||||
|
|
||||||
``render_to_response``
|
``render_to_response``
|
||||||
======================
|
======================
|
||||||
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
{{ foo }}.{{ bar }}.{{ baz }}.{{ processors }}
|
{{ foo }}.{{ bar }}.{{ baz }}.{{ STATIC_URL }}
|
||||||
|
|
|
@ -5,5 +5,6 @@ from generic.date_based import *
|
||||||
from generic.object_list import *
|
from generic.object_list import *
|
||||||
from generic.simple import *
|
from generic.simple import *
|
||||||
from i18n import *
|
from i18n import *
|
||||||
|
from shortcuts import *
|
||||||
from specials import *
|
from specials import *
|
||||||
from static import *
|
from static import *
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
from django.conf import settings
|
||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
class ShortcutTests(TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.old_STATIC_URL = settings.STATIC_URL
|
||||||
|
self.old_TEMPLATE_CONTEXT_PROCESSORS = settings.TEMPLATE_CONTEXT_PROCESSORS
|
||||||
|
|
||||||
|
settings.STATIC_URL = '/path/to/static/media'
|
||||||
|
settings.TEMPLATE_CONTEXT_PROCESSORS = (
|
||||||
|
'django.core.context_processors.static'
|
||||||
|
)
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
settings.STATIC_URL = self.old_STATIC_URL
|
||||||
|
settings.TEMPLATE_CONTEXT_PROCESSORS = self.old_TEMPLATE_CONTEXT_PROCESSORS
|
||||||
|
|
||||||
|
def test_render_to_response(self):
|
||||||
|
response = self.client.get('/views/shortcuts/render_to_response/')
|
||||||
|
self.assertEquals(response.status_code, 200)
|
||||||
|
self.assertEquals(response.content, 'FOO.BAR..\n')
|
||||||
|
self.assertEquals(response['Content-Type'], 'text/html; charset=utf-8')
|
||||||
|
|
||||||
|
def test_render_to_response_with_request_context(self):
|
||||||
|
response = self.client.get('/views/shortcuts/render_to_response/request_context/')
|
||||||
|
self.assertEquals(response.status_code, 200)
|
||||||
|
self.assertEquals(response.content, 'FOO.BAR../path/to/static/media\n')
|
||||||
|
self.assertEquals(response['Content-Type'], 'text/html; charset=utf-8')
|
||||||
|
|
||||||
|
def test_render_to_response_with_mimetype(self):
|
||||||
|
response = self.client.get('/views/shortcuts/render_to_response/mimetype/')
|
||||||
|
self.assertEquals(response.status_code, 200)
|
||||||
|
self.assertEquals(response.content, 'FOO.BAR..\n')
|
||||||
|
self.assertEquals(response['Content-Type'], 'application/x-rendertest')
|
||||||
|
|
||||||
|
def test_render(self):
|
||||||
|
response = self.client.get('/views/shortcuts/render/')
|
||||||
|
self.assertEquals(response.status_code, 200)
|
||||||
|
self.assertEquals(response.content, 'FOO.BAR../path/to/static/media\n')
|
||||||
|
self.assertEquals(response['Content-Type'], 'text/html; charset=utf-8')
|
||||||
|
|
||||||
|
def test_render_with_base_context(self):
|
||||||
|
response = self.client.get('/views/shortcuts/render/base_context/')
|
||||||
|
self.assertEquals(response.status_code, 200)
|
||||||
|
self.assertEquals(response.content, 'FOO.BAR..\n')
|
||||||
|
self.assertEquals(response['Content-Type'], 'text/html; charset=utf-8')
|
||||||
|
|
||||||
|
def test_render_with_mimetype(self):
|
||||||
|
response = self.client.get('/views/shortcuts/render/mimetype/')
|
||||||
|
self.assertEquals(response.status_code, 200)
|
||||||
|
self.assertEquals(response.content, 'FOO.BAR../path/to/static/media\n')
|
||||||
|
self.assertEquals(response['Content-Type'], 'application/x-rendertest')
|
||||||
|
|
|
@ -143,6 +143,14 @@ urlpatterns += patterns('django.views.generic.simple',
|
||||||
urlpatterns += patterns('regressiontests.views.views',
|
urlpatterns += patterns('regressiontests.views.views',
|
||||||
url(r'view_exception/(?P<n>\d+)/$', 'view_exception', name='view_exception'),
|
url(r'view_exception/(?P<n>\d+)/$', 'view_exception', name='view_exception'),
|
||||||
url(r'template_exception/(?P<n>\d+)/$', 'template_exception', name='template_exception'),
|
url(r'template_exception/(?P<n>\d+)/$', 'template_exception', name='template_exception'),
|
||||||
|
|
||||||
|
(r'^shortcuts/render_to_response/$', 'render_to_response_view'),
|
||||||
|
(r'^shortcuts/render_to_response/request_context/$', 'render_to_response_view_with_request_context'),
|
||||||
|
(r'^shortcuts/render_to_response/mimetype/$', 'render_to_response_view_with_mimetype'),
|
||||||
|
(r'^shortcuts/render/$', 'render_view'),
|
||||||
|
(r'^shortcuts/render/base_context/$', 'render_view_with_base_context'),
|
||||||
|
(r'^shortcuts/render/mimetype/$', 'render_view_with_mimetype'),
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# simple generic views.
|
# simple generic views.
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from django.http import HttpResponse, HttpResponseRedirect
|
|
||||||
from django import forms
|
from django import forms
|
||||||
|
from django.http import HttpResponse, HttpResponseRedirect
|
||||||
|
from django.core.urlresolvers import get_resolver
|
||||||
|
from django.shortcuts import render_to_response, render
|
||||||
|
from django.template import Context, RequestContext
|
||||||
from django.views.debug import technical_500_response
|
from django.views.debug import technical_500_response
|
||||||
from django.views.generic.create_update import create_object
|
from django.views.generic.create_update import create_object
|
||||||
from django.core.urlresolvers import get_resolver
|
|
||||||
from django.shortcuts import render_to_response
|
|
||||||
|
|
||||||
from regressiontests.views import BrokenException, except_args
|
from regressiontests.views import BrokenException, except_args
|
||||||
|
|
||||||
|
@ -57,3 +58,40 @@ def template_exception(request, n):
|
||||||
return render_to_response('debug/template_exception.html',
|
return render_to_response('debug/template_exception.html',
|
||||||
{'arg': except_args[int(n)]})
|
{'arg': except_args[int(n)]})
|
||||||
|
|
||||||
|
# Some views to exercise the shortcuts
|
||||||
|
|
||||||
|
def render_to_response_view(request):
|
||||||
|
return render_to_response('debug/render_test.html', {
|
||||||
|
'foo': 'FOO',
|
||||||
|
'bar': 'BAR',
|
||||||
|
})
|
||||||
|
|
||||||
|
def render_to_response_view_with_request_context(request):
|
||||||
|
return render_to_response('debug/render_test.html', {
|
||||||
|
'foo': 'FOO',
|
||||||
|
'bar': 'BAR',
|
||||||
|
}, context_instance=RequestContext(request))
|
||||||
|
|
||||||
|
def render_to_response_view_with_mimetype(request):
|
||||||
|
return render_to_response('debug/render_test.html', {
|
||||||
|
'foo': 'FOO',
|
||||||
|
'bar': 'BAR',
|
||||||
|
}, mimetype='application/x-rendertest')
|
||||||
|
|
||||||
|
def render_view(request):
|
||||||
|
return render(request, 'debug/render_test.html', {
|
||||||
|
'foo': 'FOO',
|
||||||
|
'bar': 'BAR',
|
||||||
|
})
|
||||||
|
|
||||||
|
def render_view_with_base_context(request):
|
||||||
|
return render(request, 'debug/render_test.html', {
|
||||||
|
'foo': 'FOO',
|
||||||
|
'bar': 'BAR',
|
||||||
|
}, context_instance=Context())
|
||||||
|
|
||||||
|
def render_view_with_mimetype(request):
|
||||||
|
return render(request, 'debug/render_test.html', {
|
||||||
|
'foo': 'FOO',
|
||||||
|
'bar': 'BAR',
|
||||||
|
}, mimetype='application/x-rendertest')
|
||||||
|
|
Loading…
Reference in New Issue