mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-02-02 20:54:42 +03:00
HTMLTemplateRenderer working
This commit is contained in:
parent
4af7fb96f7
commit
26c7d6df6c
|
@ -127,7 +127,7 @@ For example:
|
||||||
# and additionally requiresa 'template_name'.
|
# and additionally requiresa 'template_name'.
|
||||||
# It does not require serialization.
|
# It does not require serialization.
|
||||||
data = {'users': queryset}
|
data = {'users': queryset}
|
||||||
return Response(data, template='list_users.html')
|
return Response(data, template_name='list_users.html')
|
||||||
|
|
||||||
# JSONRenderer requires serialized data as normal.
|
# JSONRenderer requires serialized data as normal.
|
||||||
serializer = UserSerializer(instance=queryset)
|
serializer = UserSerializer(instance=queryset)
|
||||||
|
|
|
@ -10,6 +10,7 @@ from django import forms
|
||||||
from django.template import RequestContext, loader
|
from django.template import RequestContext, loader
|
||||||
from django.utils import simplejson as json
|
from django.utils import simplejson as json
|
||||||
from rest_framework.compat import yaml
|
from rest_framework.compat import yaml
|
||||||
|
from rest_framework.exceptions import ConfigurationError
|
||||||
from rest_framework.settings import api_settings
|
from rest_framework.settings import api_settings
|
||||||
from rest_framework.request import clone_request
|
from rest_framework.request import clone_request
|
||||||
from rest_framework.utils import dict2xml
|
from rest_framework.utils import dict2xml
|
||||||
|
@ -142,19 +143,41 @@ class HTMLTemplateRenderer(BaseRenderer):
|
||||||
|
|
||||||
media_type = 'text/html'
|
media_type = 'text/html'
|
||||||
format = 'html'
|
format = 'html'
|
||||||
template = None
|
template_name = None
|
||||||
|
|
||||||
def render(self, data=None, accepted_media_type=None):
|
def render(self, data=None, accepted_media_type=None):
|
||||||
"""
|
"""
|
||||||
Renders *obj* using the :attr:`template` specified on the class.
|
Renders data to HTML, using Django's standard template rendering.
|
||||||
"""
|
|
||||||
if data is None:
|
|
||||||
return ''
|
|
||||||
|
|
||||||
template = loader.get_template(self.template)
|
The template name is determined by (in order of preference):
|
||||||
context = RequestContext(self.view.request, {'object': data})
|
|
||||||
|
1. An explicit .template_name set on the response.
|
||||||
|
2. An explicit .template_name set on this class.
|
||||||
|
3. The return result of calling view.get_template_names().
|
||||||
|
"""
|
||||||
|
view = self.view
|
||||||
|
request, response = view.request, view.response
|
||||||
|
|
||||||
|
template_names = self.get_template_names(response, view)
|
||||||
|
template = self.resolve_template(template_names)
|
||||||
|
context = self.resolve_context(data, request)
|
||||||
return template.render(context)
|
return template.render(context)
|
||||||
|
|
||||||
|
def resolve_template(self, template_names):
|
||||||
|
return loader.select_template(template_names)
|
||||||
|
|
||||||
|
def resolve_context(self, data, request):
|
||||||
|
return RequestContext(request, data)
|
||||||
|
|
||||||
|
def get_template_names(self, response, view):
|
||||||
|
if response.template_name:
|
||||||
|
return [response.template_name]
|
||||||
|
elif self.template_name:
|
||||||
|
return [self.template_name]
|
||||||
|
elif hasattr(view, 'get_template_names'):
|
||||||
|
return view.get_template_names()
|
||||||
|
raise ConfigurationError('Returned a template response with no template_name')
|
||||||
|
|
||||||
|
|
||||||
class DocumentingHTMLRenderer(BaseRenderer):
|
class DocumentingHTMLRenderer(BaseRenderer):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -8,8 +8,8 @@ class Response(SimpleTemplateResponse):
|
||||||
arbitrary media types.
|
arbitrary media types.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, data=None, status=None, headers=None,
|
def __init__(self, data=None, status=None,
|
||||||
renderer=None, accepted_media_type=None):
|
template_name=None, headers=None):
|
||||||
"""
|
"""
|
||||||
Alters the init arguments slightly.
|
Alters the init arguments slightly.
|
||||||
For example, drop 'template_name', and instead use 'data'.
|
For example, drop 'template_name', and instead use 'data'.
|
||||||
|
@ -20,21 +20,21 @@ class Response(SimpleTemplateResponse):
|
||||||
super(Response, self).__init__(None, status=status)
|
super(Response, self).__init__(None, status=status)
|
||||||
self.data = data
|
self.data = data
|
||||||
self.headers = headers and headers[:] or []
|
self.headers = headers and headers[:] or []
|
||||||
|
self.template_name = template_name
|
||||||
self.accepted_renderer = renderer
|
|
||||||
self.accepted_media_type = accepted_media_type
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def rendered_content(self):
|
def rendered_content(self):
|
||||||
renderer = self.accepted_renderer
|
renderer = self.accepted_renderer
|
||||||
|
media_type = self.accepted_media_type
|
||||||
|
|
||||||
assert renderer, "No renderer set on Response"
|
assert renderer, "No accepted renderer set on Response"
|
||||||
|
assert media_type, "No accepted media type set on Response"
|
||||||
|
|
||||||
self['content-type'] = self.accepted_media_type
|
self['content-type'] = media_type
|
||||||
if self.data is None:
|
if self.data is None:
|
||||||
return renderer.render()
|
return renderer.render()
|
||||||
|
|
||||||
return renderer.render(self.data, self.accepted_media_type)
|
return renderer.render(self.data, media_type)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def status_text(self):
|
def status_text(self):
|
||||||
|
|
50
rest_framework/tests/htmlrenderer.py
Normal file
50
rest_framework/tests/htmlrenderer.py
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
from django.conf.urls.defaults import patterns, url
|
||||||
|
from django.test import TestCase
|
||||||
|
from django.template import TemplateDoesNotExist, Template
|
||||||
|
import django.template.loader
|
||||||
|
from rest_framework.decorators import api_view, renderer_classes
|
||||||
|
from rest_framework.renderers import HTMLTemplateRenderer
|
||||||
|
from rest_framework.response import Response
|
||||||
|
|
||||||
|
|
||||||
|
@api_view(('GET',))
|
||||||
|
@renderer_classes((HTMLTemplateRenderer,))
|
||||||
|
def example(request):
|
||||||
|
"""
|
||||||
|
A view that can returns an HTML representation.
|
||||||
|
"""
|
||||||
|
data = {'object': 'foobar'}
|
||||||
|
return Response(data, template_name='example.html')
|
||||||
|
|
||||||
|
|
||||||
|
urlpatterns = patterns('',
|
||||||
|
url(r'^$', example),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class HTMLRendererTests(TestCase):
|
||||||
|
urls = 'rest_framework.tests.htmlrenderer'
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
"""
|
||||||
|
Monkeypatch get_template
|
||||||
|
"""
|
||||||
|
self.get_template = django.template.loader.get_template
|
||||||
|
|
||||||
|
def get_template(template_name):
|
||||||
|
if template_name == 'example.html':
|
||||||
|
return Template("example: {{ object }}")
|
||||||
|
raise TemplateDoesNotExist(template_name)
|
||||||
|
|
||||||
|
django.template.loader.get_template = get_template
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
"""
|
||||||
|
Revert monkeypatching
|
||||||
|
"""
|
||||||
|
django.template.loader.get_template = self.get_template
|
||||||
|
|
||||||
|
def test_simple_html_view(self):
|
||||||
|
response = self.client.get('/')
|
||||||
|
self.assertContains(response, "example: foobar")
|
||||||
|
self.assertEquals(response['content-type'], 'text/html')
|
Loading…
Reference in New Issue
Block a user