Skip to content

Instantly share code, notes, and snippets.

@silenius
Created March 3, 2015 15:12
Show Gist options
  • Save silenius/d2d18490c075689a1f54 to your computer and use it in GitHub Desktop.
Save silenius/d2d18490c075689a1f54 to your computer and use it in GitHub Desktop.
# -*- 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