Created
March 3, 2015 15:12
-
-
Save silenius/d2d18490c075689a1f54 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
import cherrypy | |
from cherrypy._cpdispatch import Dispatcher | |
from sqlalchemy import sql | |
from amnesia import db | |
__all__ = ['AmnesiaDispatcher'] | |
class AmnesiaDispatcher(Dispatcher): | |
""" | |
This dispatcher uses a mapping procedure based on the content type of an | |
entity. The ID of the entity should always come first in the path info. | |
It performs the following steps: | |
- check if the id can be found in the path info and is valid | |
- query the database to get the corresponding content type | |
- adapt (transform) the path info and call the default dispatcher to | |
find the handler. | |
For example, if object with id=90 is a "page": | |
- /90 => /page/show/90 | |
- /90/show => /page/show/90 | |
- /90/edit => /page/edit/90 | |
- /90.json => /page/show/90 (add "X-Accept" header with | |
"application/json") | |
- /90.xml => /page/show/90 (adapt "X-Accept" header with | |
"application/xml") | |
- ... | |
""" | |
accepts = { | |
'json' : 'application/json', | |
'xml' : 'application/xml' | |
} | |
q = '''SELECT ct.name FROM content c JOIN content_type ct ON | |
c.content_type_id = ct.id AND c.id = :id''' | |
def __call__(self, path_info): | |
_path_info = [x for x in path_info.strip('/').split('/', 2) if x] | |
if _path_info: | |
# Do we have 123 or 123.json or ... ? | |
obj_id = _path_info[0].split('.', 1) | |
if len(obj_id) == 2: | |
# 123.json | |
(obj_id, content_type) = obj_id | |
else: | |
# 123 | |
(obj_id, content_type) = (obj_id[0], None) | |
if obj_id.isdigit(): | |
# "show" is the default action | |
if not len(_path_info) > 1: | |
_path_info.append('show') | |
_path_info.insert(2, obj_id) | |
# Fetch content type for obj_id | |
r = db.Session.execute(self.q, {'id' : obj_id}).fetchone() | |
if r: | |
_path_info[0] = r.name.replace(' ', '_') | |
if content_type in self.accepts: | |
cherrypy.request.headers['X-Accept'] = self.accepts[content_type] | |
return super(AmnesiaDispatcher, self).__call__('/'.join(_path_info)) | |
raise cherrypy.NotFound() | |
return super(AmnesiaDispatcher, self).__call__(path_info) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment