Pyramid Hybrid application (traversal + url dispatch) -
i've started using pyramid , have best-practice/general-concept questions it's hybrid application approach. let me try mock small complex scenario i'm trying do...
scenario
say i'm building website movies, place users can go add movies, them , other stuff them. here's desired functionality:
/renderstemplates/root.html/moviesrenderstemplates/default.html, shows list of movies/movies/123456shows details movie/movies/123456/usersshows list of users edited movie/usersrenderstemplates/default.html, shows list of users/users/654321shows details user/users/654321/moviesshows list of favorite movies user/reviews/moviesrenderstemplates/reviews.html, shows url_fetched movie reviews/adminplace can log in , change stuff/admin/moviesrenderstemplates/admin.html, shows list of editable movies/admin/movies/123456renderstemplates/form.html, edit movie
extras:
- ability handle nested resources, example
movies/123/similar/234/similar/345, similar property of movie class lists ids of related movies. or maybe more clear example be:companies/123/partners/234/clients/345... /movies/123456.jsondetails movie in json format/movies/123456.xmldetails movie in xml format- restfull methods (get, put, delete..) authorization headers resource handling
approach
this i've done far (my views class based, simplicity, i'll list decorators...):
# resources.py class root(object): __name__ = __parent__ = none def __getitem__(self, name): return none def factory(request): # pseudo code... # checks database model that's resource if modelresource: return modelresource() return root() # main.py def notfound(request): return httpnotfound() def wsgi_app(): config = configurator() config.add_translation_dirs('locale',) config.add_renderer('.html', jinja2renderer) # static config.add_static_view('static', 'static') # root config.add_route('root', '/') # admin config.add_route('admin', '/admin/*traverse', factory='factory') config.add_route('default', '/{path}/*traverse', factory='factory') config.add_notfound_view(notfound, append_slash=true) config.scan('views') return config.make_wsgi_app() # views/root.py @view_config(route_name='root', renderer="root.html") def __call__(): # views/default.py @view_defaults(route_name='default') class defaultview(baseview): @view_config(context=modelresource, renderer="default.html") def with_context(): @view_config() def __call__(): # views/admin.py @view_defaults(route_name='admin') class adminview(baseview): @view_config(context=modelresource, renderer="admin.html") def default(self): @view_config(renderer="admin.html") def __call__(self): and following piece of code real app. modelresource used context view lookup, , reason post... since models (i'm working google app engine datastore) have same basic functionality extend specific superclass. first instinct add traversal functionality @ level, that's why created modelresource (additional explanation in code comments), i'm begining regret :) i'm looking insight , ideas how handle this.
class modelresource(ndb.model): def __getitem__(self, name): module = next(module module in application.modules if module.get('class') == self.__class__.__name__) # can read as: if name == 'movies' or name == 'users' or ..... if name in module.get('nodes'): # setup can set application.modules[0]['nodes'] = [u'movies', u'films', u'фильми' ] # , use of defined alternatives find resource # return empty instance of resource can queried in view return self # models use unique numerical ids elif re.match(r'\d+', name): # return instance supplied id cls = self.__class__ return cls.get_by_id(name) # attempt solve nesting issue # if model has repeated property should return class # of child item(s) # i'm displaying property's value... elif hasattr(self, name): # todo: ndb.keyproperty, ndb.structuredproperty return getattr(self, name) # option find resource slug instead of id... elif re.match(r'\w+', name): cls = self.__class__ instance = cls.query(cls.slug == name).get() if instance: return instance raise keyerror questions
i have 2 big questions (widh sub-questions):
how should handle traversal in described scenario?
- should extend class, or implement interface, or else?
- should traversal handled @ model level (movie model, or it's superclass have
__getitem__method)? should resource model instance? - what's best practice
__getitem__returns collection (list) of resources? in scenario/movies/ - my modelresource in code above not location aware... i'm having trouble getting
__public__,__name__work, because wrong way traversal :) i'm guessing once find right way, nested resources shouldn't problem.
how can switch back traversal url dispatching?
- for stuff: how can set different renderer handle json requests? before added traversal configured
config.add_route('json', '/{path:.*}.json'), worked appropriate view, route never matched... - same problem above - added view handles http methods
@view_config(request_method='get'), it's never matched in configuration.
- for stuff: how can set different renderer handle json requests? before added traversal configured
sorry long post, it's complex scenario. should mention real app has 10-15 models atm, i'm looking solution handle in 1 place - want avoid manually setting resource tree...
Comments
Post a Comment