Add styling and urlizing to html views of resources

This commit is contained in:
Tom Christie 2010-12-30 13:52:46 +00:00
parent 8a12f89aaa
commit abb55a4909
9 changed files with 130 additions and 11 deletions

View File

@ -1,6 +1,8 @@
from django.http import HttpResponse from django.http import HttpResponse
from decimal import Decimal from django.core.urlresolvers import reverse
from rest import emitters, parsers from rest import emitters, parsers
from decimal import Decimal
class Resource(object): class Resource(object):
@ -29,6 +31,7 @@ class Resource(object):
def __new__(cls, request, *args, **kwargs): def __new__(cls, request, *args, **kwargs):
self = object.__new__(cls) self = object.__new__(cls)
self.__init__() self.__init__()
self._request = request
return self._handle_request(request, *args, **kwargs) return self._handle_request(request, *args, **kwargs)
def __init__(self): def __init__(self):
@ -145,3 +148,8 @@ class Resource(object):
def delete(self, headers={}, *args, **kwargs): def delete(self, headers={}, *args, **kwargs):
return self._not_implemented('delete') return self._not_implemented('delete')
def reverse(self, view, *args, **kwargs):
"""Return a fully qualified URI for a view, using the current request as the base URI.
"""
return self._request.build_absolute_uri(reverse(view, *args, **kwargs))

View File

@ -1,11 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?> {% load urlize_quoted_links %}<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"> <html xmlns="http://www.w3.org/1999/xhtml">
<head>
<style>
pre {border: 1px solid black; padding: 1em; background: #ffd}
</style>
</head>
<body> <body>
<h1>{{ resource_name }}</h1> <h1>{{ resource_name }}</h1>
<p>{{ resource_doc }}</p> <p>{{ resource_doc }}</p>
<pre> <pre>{% autoescape off %}HTTP Status {{ status }}
{% include 'emitter.txt' %} </pre> {% for key, val in headers.items %}{{ key }}: {{ val }}
{% endfor %}
{{ content|urlize_quoted_links }}{% endautoescape %} </pre>
</body> </body>
</html> </html>

View File

Binary file not shown.

View File

@ -0,0 +1,96 @@
"""Adds the custom filter 'urlize_quoted_links'
This is identical to the built-in filter 'urlize' with the exception that
single and double quotes are permitted as leading or trailing punctuation.
"""
# Almost all of this code is copied verbatim from django.utils.html
# LEADING_PUNCTUATION and TRAILING_PUNCTUATION have been modified
import re
import string
from django.utils.safestring import SafeData, mark_safe
from django.utils.encoding import force_unicode
from django.utils.http import urlquote
from django.utils.html import escape
from django import template
# Configuration for urlize() function.
LEADING_PUNCTUATION = ['(', '<', '&lt;', '"', "'"]
TRAILING_PUNCTUATION = ['.', ',', ')', '>', '\n', '&gt;', '"', "'"]
# List of possible strings used for bullets in bulleted lists.
DOTS = ['&middot;', '*', '\xe2\x80\xa2', '&#149;', '&bull;', '&#8226;']
unencoded_ampersands_re = re.compile(r'&(?!(\w+|#\d+);)')
word_split_re = re.compile(r'(\s+)')
punctuation_re = re.compile('^(?P<lead>(?:%s)*)(?P<middle>.*?)(?P<trail>(?:%s)*)$' % \
('|'.join([re.escape(x) for x in LEADING_PUNCTUATION]),
'|'.join([re.escape(x) for x in TRAILING_PUNCTUATION])))
simple_email_re = re.compile(r'^\S+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+$')
link_target_attribute_re = re.compile(r'(<a [^>]*?)target=[^\s>]+')
html_gunk_re = re.compile(r'(?:<br clear="all">|<i><\/i>|<b><\/b>|<em><\/em>|<strong><\/strong>|<\/?smallcaps>|<\/?uppercase>)', re.IGNORECASE)
hard_coded_bullets_re = re.compile(r'((?:<p>(?:%s).*?[a-zA-Z].*?</p>\s*)+)' % '|'.join([re.escape(x) for x in DOTS]), re.DOTALL)
trailing_empty_content_re = re.compile(r'(?:<p>(?:&nbsp;|\s|<br \/>)*?</p>\s*)+\Z')
def urlize_quoted_links(text, trim_url_limit=None, nofollow=False, autoescape=False):
"""
Converts any URLs in text into clickable links.
Works on http://, https://, www. links and links ending in .org, .net or
.com. Links can have trailing punctuation (periods, commas, close-parens)
and leading punctuation (opening parens) and it'll still do the right
thing.
If trim_url_limit is not None, the URLs in link text longer than this limit
will truncated to trim_url_limit-3 characters and appended with an elipsis.
If nofollow is True, the URLs in link text will get a rel="nofollow"
attribute.
If autoescape is True, the link text and URLs will get autoescaped.
"""
trim_url = lambda x, limit=trim_url_limit: limit is not None and (len(x) > limit and ('%s...' % x[:max(0, limit - 3)])) or x
safe_input = isinstance(text, SafeData)
words = word_split_re.split(force_unicode(text))
nofollow_attr = nofollow and ' rel="nofollow"' or ''
for i, word in enumerate(words):
match = None
if '.' in word or '@' in word or ':' in word:
match = punctuation_re.match(word)
if match:
lead, middle, trail = match.groups()
# Make URL we want to point to.
url = None
if middle.startswith('http://') or middle.startswith('https://'):
url = urlquote(middle, safe='/&=:;#?+*')
elif middle.startswith('www.') or ('@' not in middle and \
middle and middle[0] in string.ascii_letters + string.digits and \
(middle.endswith('.org') or middle.endswith('.net') or middle.endswith('.com'))):
url = urlquote('http://%s' % middle, safe='/&=:;#?+*')
elif '@' in middle and not ':' in middle and simple_email_re.match(middle):
url = 'mailto:%s' % middle
nofollow_attr = ''
# Make link.
if url:
trimmed = trim_url(middle)
if autoescape and not safe_input:
lead, trail = escape(lead), escape(trail)
url, trimmed = escape(url), escape(trimmed)
middle = '<a href="%s"%s>%s</a>' % (url, nofollow_attr, trimmed)
words[i] = mark_safe('%s%s%s' % (lead, middle, trail))
else:
if safe_input:
words[i] = mark_safe(word)
elif autoescape:
words[i] = escape(word)
elif safe_input:
words[i] = mark_safe(word)
elif autoescape:
words[i] = escape(word)
return u''.join(words)
# Register urlize_quoted_links as a custom filter
# http://docs.djangoproject.com/en/dev/howto/custom-template-tags/
register = template.Library()
register.filter(urlize_quoted_links)

Binary file not shown.

View File

@ -1,8 +1,7 @@
from django.conf.urls.defaults import patterns from django.conf.urls.defaults import patterns
from testapp.views import ReadOnlyResource, MirroringWriteResource
urlpatterns = patterns('testapp.views',
urlpatterns = patterns('', (r'^$', 'RootResource'),
(r'^read-only$', ReadOnlyResource), (r'^read-only$', 'ReadOnlyResource'),
(r'^mirroring-write$', MirroringWriteResource), (r'^mirroring-write$', 'MirroringWriteResource'),
) )

View File

@ -1,6 +1,15 @@
from decimal import Decimal
from rest.resource import Resource from rest.resource import Resource
class RootResource(Resource):
"""This is my docstring
"""
allowed_methods = ('GET',)
def read(self, headers={}, *args, **kwargs):
return (200, {'read-only-api': self.reverse(ReadOnlyResource),
'write-only-api': self.reverse(MirroringWriteResource)}, {})
class ReadOnlyResource(Resource): class ReadOnlyResource(Resource):
"""This is my docstring """This is my docstring
""" """

View File

@ -5,7 +5,7 @@ admin.autodiscover()
urlpatterns = patterns('', urlpatterns = patterns('',
# Example: # Example:
(r'^testapp/', include('testapp.urls')), (r'^', include('testapp.urls')),
# Uncomment the admin/doc line below to enable admin documentation: # Uncomment the admin/doc line below to enable admin documentation:
(r'^admin/doc/', include('django.contrib.admindocs.urls')), (r'^admin/doc/', include('django.contrib.admindocs.urls')),