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 decimal import Decimal
from django.core.urlresolvers import reverse
from rest import emitters, parsers
from decimal import Decimal
class Resource(object):
@ -29,6 +31,7 @@ class Resource(object):
def __new__(cls, request, *args, **kwargs):
self = object.__new__(cls)
self.__init__()
self._request = request
return self._handle_request(request, *args, **kwargs)
def __init__(self):
@ -145,3 +148,8 @@ class Resource(object):
def delete(self, headers={}, *args, **kwargs):
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"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<style>
pre {border: 1px solid black; padding: 1em; background: #ffd}
</style>
</head>
<body>
<h1>{{ resource_name }}</h1>
<p>{{ resource_doc }}</p>
<pre>
{% include 'emitter.txt' %} </pre>
<pre>{% autoescape off %}HTTP Status {{ status }}
{% for key, val in headers.items %}{{ key }}: {{ val }}
{% endfor %}
{{ content|urlize_quoted_links }}{% endautoescape %} </pre>
</body>
</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 testapp.views import ReadOnlyResource, MirroringWriteResource
urlpatterns = patterns('',
(r'^read-only$', ReadOnlyResource),
(r'^mirroring-write$', MirroringWriteResource),
urlpatterns = patterns('testapp.views',
(r'^$', 'RootResource'),
(r'^read-only$', 'ReadOnlyResource'),
(r'^mirroring-write$', 'MirroringWriteResource'),
)

View File

@ -1,6 +1,15 @@
from decimal import Decimal
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):
"""This is my docstring
"""

View File

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