[open-ils-commits] r168 - in servres/trunk/conifer: . static syrup templates templates/components templates/feeds (gfawcett)
svn at svn.open-ils.org
svn at svn.open-ils.org
Thu Mar 12 21:57:32 EDT 2009
Author: gfawcett
Date: 2009-03-12 21:57:31 -0400 (Thu, 12 Mar 2009)
New Revision: 168
Added:
servres/trunk/conifer/templates/feeds/
servres/trunk/conifer/templates/feeds/course_atom.xml
servres/trunk/conifer/templates/feeds/course_feed_index.xhtml
Modified:
servres/trunk/conifer/genshi_support.py
servres/trunk/conifer/static/main.css
servres/trunk/conifer/syrup/models.py
servres/trunk/conifer/syrup/urls.py
servres/trunk/conifer/syrup/views.py
servres/trunk/conifer/templates/components/course.xhtml
Log:
Feeds! Atom feeds for course-site items.
Some notes:
* all feeds are Atom; comments on my Atom details are welcome.
* several different feeds per course site. E.g., just top-level items;
recently-changed items; a walk of all items in the site directory
tree; many others possible.
* by design, the feeds themselves are anonymous-access. I don't see a
real security risk here, but if exposing titles and modification
dates violates some policy, we can change it.
* all links in the feeds refer back to the Reserves system, so they
can be authenticated if necessary. This is also true for "URL items"
-- the Atom link is back to the canonical item-URL in Reserves,
which redirects to the target URL (if you're allowed to know it).
* Django has its own feed system. I tried it, and then chose not to
use it. Genshi does a fine job, and IMHO Django makes it harder to
offer multiple feed-variants on individual items like Courses. It
looks good for simpler feed-needs though, and has the benefit of
supporting both Atom and RSS. (Not that we couldn't do that with
Genshi too.)
There's room for more feed types: "My Courses", "Things in My
Courses", "canned search", etc. Ideas are most welcome.
Modified: servres/trunk/conifer/genshi_support.py
===================================================================
--- servres/trunk/conifer/genshi_support.py 2009-03-12 22:44:40 UTC (rev 167)
+++ servres/trunk/conifer/genshi_support.py 2009-03-13 01:57:31 UTC (rev 168)
@@ -43,8 +43,8 @@
#------------------------------------------------------------
# main API
-def render(tname, _django_type=HttpResponse, **kwargs):
+def render(tname, _django_type=HttpResponse, _serialization='xhtml', **kwargs):
request = get_request()
_inject_django_things_into_namespace(request, kwargs)
- return _django_type(template(tname).generate(**kwargs).render('xhtml'))
+ return _django_type(template(tname).generate(**kwargs).render(_serialization))
Modified: servres/trunk/conifer/static/main.css
===================================================================
--- servres/trunk/conifer/static/main.css 2009-03-12 22:44:40 UTC (rev 167)
+++ servres/trunk/conifer/static/main.css 2009-03-13 01:57:31 UTC (rev 168)
@@ -199,6 +199,8 @@
#edit_course_link { margin: 8 0 8 0; font-size: 95%; }
+#feeds_panel { float: right; font-size: 95%; margin: 8 0; }
+
.breadcrumbs { margin: 8 8 8 0; }
.errorlist { float: right; }
Modified: servres/trunk/conifer/syrup/models.py
===================================================================
--- servres/trunk/conifer/syrup/models.py 2009-03-12 22:44:40 UTC (rev 167)
+++ servres/trunk/conifer/syrup/models.py 2009-03-13 01:57:31 UTC (rev 168)
@@ -422,7 +422,7 @@
date_created = m.DateTimeField(auto_now_add=True)
- last_modified = m.DateTimeField()
+ last_modified = m.DateTimeField(auto_now=True)
def title_hl(self, terms):
hl_title = self.title
@@ -458,12 +458,12 @@
return self.item_type in ('ELEC', 'URL')
- def item_url(self, suffix=''):
+ def item_url(self, suffix='', force_local_url=False):
if self.item_type == 'ELEC' and suffix == '':
return '/syrup/course/%d/item/%d/dl/%s' % (
self.course_id, self.id,
self.fileobj.name.split('/')[-1])
- if self.item_type == 'URL' and suffix == '':
+ if self.item_type == 'URL' and suffix == '' and not force_local_url:
return self.url
else:
return '/syrup/course/%d/item/%d/%s' % (
Modified: servres/trunk/conifer/syrup/urls.py
===================================================================
--- servres/trunk/conifer/syrup/urls.py 2009-03-12 22:44:40 UTC (rev 167)
+++ servres/trunk/conifer/syrup/urls.py 2009-03-13 01:57:31 UTC (rev 168)
@@ -26,6 +26,7 @@
(r'^course/(?P<course_id>\d+)/edit/$', 'edit_course'),
(r'^course/(?P<course_id>\d+)/edit/delete/$', 'delete_course'),
(r'^course/(?P<course_id>\d+)/edit/permission/$', 'edit_course_permissions'),
+ (r'^course/(?P<course_id>\d+)/feeds/(?P<feed_type>.*)$', 'course_feeds'),
(ITEM_PREFIX + r'$', 'item_detail'),
(ITEM_PREFIX + r'dl/(?P<filename>.*)$', 'item_download'),
(ITEM_PREFIX + r'meta$', 'item_metadata'),
@@ -35,7 +36,6 @@
(r'^admin/terms/' + GENERIC_REGEX, 'admin_terms'),
(r'^admin/depts/' + GENERIC_REGEX, 'admin_depts'),
(r'^admin/news/' + GENERIC_REGEX, 'admin_news'),
-
# (r'^admin/terms/(?P<term_id>\d+)/$', 'admin_term_edit'),
# (r'^admin/terms/(?P<term_id>\d+)/delete$', 'admin_term_delete'),
# (r'^admin/terms/$', 'admin_term'),
Modified: servres/trunk/conifer/syrup/views.py
===================================================================
--- servres/trunk/conifer/syrup/views.py 2009-03-12 22:44:40 UTC (rev 167)
+++ servres/trunk/conifer/syrup/views.py 2009-03-13 01:57:31 UTC (rev 168)
@@ -156,6 +156,11 @@
return _access_denied(_('Only administrators are allowed here.'))
return hdlr
+#decorator
+def public(handler):
+ # A no-op! Just here to be used to explicitly decorate methods
+ # that are supposed to be public.
+ return handler
#-----------------------------------------------------------------------------
def welcome(request):
@@ -838,3 +843,46 @@
clean_body = strip_and_nonblank('body')
admin_news = generic_handler(NewsForm, decorator=admin_only)
+
+
+
+#-----------------------------------------------------------------------------
+# Course feeds
+
+ at public # and proud of it!
+def course_feeds(request, course_id, feed_type):
+ course = get_object_or_404(models.Course, pk=course_id)
+ if feed_type == '':
+ return g.render('feeds/course_feed_index.xhtml',
+ course=course)
+ else:
+ items = course.items()
+ def render_title(item):
+ return item.title
+ if feed_type == 'top-level':
+ items = items.filter(parent_heading=None).order_by('-sort_order')
+ elif feed_type == 'recent-changes':
+ items = items.order_by('-last_modified')
+ elif feed_type == 'tree':
+ def flatten(nodes, acc):
+ for node in nodes:
+ item, kids = node
+ acc.append(item)
+ flatten(kids, acc)
+ return acc
+ items = flatten(course.item_tree(), [])
+ def render_title(item):
+ if item.parent_heading:
+ return '%s :: %s' % (item.parent_heading.title, item.title)
+ else:
+ return item.title
+
+ lastmod = max(i.last_modified for i in items)
+ return g.render('feeds/course_atom.xml',
+ course=course,
+ feed_type=feed_type,
+ lastmod=lastmod,
+ render_title=render_title,
+ items=items,
+ root='http://localhost:8000',
+ _serialization='xml')
Modified: servres/trunk/conifer/templates/components/course.xhtml
===================================================================
--- servres/trunk/conifer/templates/components/course.xhtml 2009-03-12 22:44:40 UTC (rev 167)
+++ servres/trunk/conifer/templates/components/course.xhtml 2009-03-13 01:57:31 UTC (rev 168)
@@ -22,6 +22,7 @@
${course_search(course)}
<h1><a href="${course.course_url()}"><span py:if="course.code">${course.code}: </span>${course.title}</a></h1>
</div>
+ <div id="feeds_panel"><a href="${course.course_url('feeds/')}">Feeds</a></div>
</div>
<!-- !show_tree: display a tree of items in a hierarchical style. -->
Added: servres/trunk/conifer/templates/feeds/course_atom.xml
===================================================================
--- servres/trunk/conifer/templates/feeds/course_atom.xml (rev 0)
+++ servres/trunk/conifer/templates/feeds/course_atom.xml 2009-03-13 01:57:31 UTC (rev 168)
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<feed xmlns="http://www.w3.org/2005/Atom"
+ xmlns:xi="http://www.w3.org/2001/XInclude"
+ xmlns:py="http://genshi.edgewall.org/">
+ <title>Reserves (${feed_type}) for ${course.list_display()}</title>
+ <link href="${root}${course.course_url()}"
+ rel="alternate"/>
+ <link href="${root}${course.course_url('feeds/' + feed_type)}"
+ rel="self"/>
+ <id>${root}${course.course_url('feeds/') + feed_type}</id>
+ <updated>${lastmod.strftime("%Y-%m-%dT%H:%M:%SZ")}</updated>
+ <entry py:for="item in items">
+ <title>${render_title(item)}</title>
+ <link href="${root}${item.item_url(force_local_url=True)}"
+ rel="alternate"></link>
+ <updated>${item.last_modified.strftime("%Y-%m-%dT%H:%M:%SZ")}</updated>
+ <id>${root}${item.item_url('')}</id>
+ <summary type="html">${item.get_item_type_display()}.
+ <div py:if="item.item_type=='HEADING'" py:strip="True">
+ Contains ${len(models.Item.objects.filter(parent_heading=item))} items.
+ </div>
+ </summary>
+ </entry>
+</feed>
Added: servres/trunk/conifer/templates/feeds/course_feed_index.xhtml
===================================================================
--- servres/trunk/conifer/templates/feeds/course_feed_index.xhtml (rev 0)
+++ servres/trunk/conifer/templates/feeds/course_feed_index.xhtml 2009-03-13 01:57:31 UTC (rev 168)
@@ -0,0 +1,22 @@
+<?python
+title = _('Available Feeds')
+?>
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:xi="http://www.w3.org/2001/XInclude"
+ xmlns:py="http://genshi.edgewall.org/">
+ <xi:include href="../master.xhtml"/>
+ <xi:include href="../components/course.xhtml"/>
+ <head>
+ <title>${title}</title>
+ <script type="text/javascript" src="/static/menublocks.js"/>
+ </head>
+ <body>
+ ${course_banner(course)}
+ <h2>Available Feeds</h2>
+ <ul>
+ <li><a href="recent-changes">Recent changes</a></li>
+ <li><a href="top-level">Top level items in this site</a></li>
+ <li><a href="tree">Tree-walk of all items in this site</a></li>
+ </ul>
+ </body>
+</html>
More information about the open-ils-commits
mailing list