root/tags/amplee-0.5.0/amplee/examples/cooker/core/browser.py

Revision 443, 5.0 kB (checked in by sylvain, 1 year ago)

Added a make_feed method to the Service class allowing to quickly construct atom feeds from a mapping of member ids (such as returned by the indexer), added a search box based on that feature to the cooker example.

Line 
1 # -*- coding: utf-8 -*-
2
3 import os.path
4 import threading
5 import cherrypy
6 import sha
7 from sets import Set
8 from urllib import unquote
9 from amplee.comparer import app_updated_comparer
10 from amplee.utils import get_isodate, \
11      compute_etag_from_feed, compute_etag_from_entry
12
13 from bridge import Element as E
14 from bridge import Document, PI
15 from bridge.common import ATOM10_NS, ATOM10_PREFIX
16
17 from core.utils import transform_member_resource
18
19 __all__ = ['Browser', 'Menu', 'Null']
20
21 class Null(object):
22     pass
23
24 class Browser(object):
25     def __init__(self, service, indexer):
26         self.service = service
27         self.indexer = indexer
28        
29     @cherrypy.expose
30     def index(self):
31         cherrypy.response.headers['content-type'] = 'application/xml'
32         return self.service.service.xml()
33
34     @cherrypy.expose
35     def search(self, query):
36         tokens = query.split(' ')
37         s = Set()
38         for token in tokens:
39             t = self.indexer.indexes['category_index'].lookup(term=token)
40             s |= t
41
42         items = self.indexer.to_dict(s)
43
44         cherrypy.response.headers['content-type'] = 'application/xml'
45         return self.service.make_feed(items, entry_processor=transform_member_resource,
46                                       title=u"Search Result", xslt_path=u"/static/search.xsl",
47                                       member_comparer=app_updated_comparer).xml()
48        
49 class Menu(object):
50     def __init__(self, collection):
51         self.collection = collection
52         self.lock = threading.Lock()
53
54     @cherrypy.expose
55     def index(self):
56         # we cannot return the feed using the proper media-type here
57         # since most browsers won't know what to do with it
58         cherrypy.response.headers['content-type'] = 'application/xml'
59         feed = self.collection.feed_handler.public_feed.xml_root
60         cherrypy.response.headers['ETag'] = compute_etag_from_feed(feed)
61         return self.collection.feed_handler.public_xml()
62
63     @cherrypy.expose
64     def default(self, recipe, comments=None, **kwargs):
65         recipe = unquote(recipe).decode('utf-8')
66         member_id, media_id = self.collection.convert_id(recipe)
67         member = self.collection.get_member(member_id)
68         if not member:
69             raise cherrypy.NotFound()
70
71         if not comments: # Recipe alone requested
72             entry = transform_member_resource(member, xslt_path="/static/entry.xsl")
73             cherrypy.response.headers['ETag'] = compute_etag_from_entry(entry.xml_root)
74             if recipe.endswith('.atom'): # The client really wants the atom entry itself
75                 cherrypy.response.headers['content-type'] = 'application/atom+xml;type=entry'
76             else:
77                 cherrypy.response.headers['content-type'] = 'application/xml'
78             return entry.xml()
79         elif cherrypy.request.method == 'GET': # Comments requested
80             path = os.path.join('static', 'replies', member.media_id)
81             if os.path.exists(path):
82                 cherrypy.response.headers['content-type'] = 'application/xml'
83                 return file(path, 'r')
84         elif cherrypy.request.method == 'POST': # New comment POSTed
85             author = kwargs.get('author', '')
86             content = kwargs.get('content', '')
87             path = os.path.join('static', 'replies', member.media_id)
88             try:
89                 self.lock.acquire()
90                 feed = E.load(file(path, 'r').read())
91                 root = feed.xml_root
92                 e = E(u'entry', namespace=ATOM10_NS, prefix=ATOM10_PREFIX, parent=root)
93                 isodate = get_isodate()
94                 E(u'id', content=u'tags:comment:%s' % sha.new(str(isodate)).hexdigest(),
95                   namespace=ATOM10_NS, prefix=ATOM10_PREFIX, parent=e)
96                 E(u'updated', content=isodate,
97                   namespace=ATOM10_NS, prefix=ATOM10_PREFIX, parent=e)
98                 E(u'title', attributes={u'type': u'text'},
99                   namespace=ATOM10_NS, prefix=ATOM10_PREFIX, parent=e)
100                 a = E(u'author', namespace=ATOM10_NS, prefix=ATOM10_PREFIX, parent=e)
101                 E(u'name', content=author.decode('utf-8'),
102                   namespace=ATOM10_NS, prefix=ATOM10_PREFIX, parent=a)
103
104                 E(u'content', content=content.decode('utf-8'),
105                   attributes={u'type': u'text'}, namespace=ATOM10_NS, prefix=ATOM10_PREFIX, parent=e)
106
107                 updated = root.get_child('updated', ATOM10_NS)
108                 updated.xml_text = isodate
109                
110                 file(path, 'w').write(feed.xml())
111             finally:
112                 self.lock.release()
113
114             raise cherrypy.HTTPRedirect(cherrypy.url())
115        
116         raise cherrypy.NotFound()
117            
118     @cherrypy.expose
119     def feed(self):
120         cherrypy.response.headers['content-type'] = 'application/atom+xml;type=feed'
121         feed = self.collection.feed_handler.public_feed.xml_root
122         cherrypy.response.headers['ETag'] = compute_etag_from_feed(feed)
123         return self.collection.feed_handler.public_xml()
124  
Note: See TracBrowser for help on using the browser.