diff --git a/buildout.cfg b/buildout.cfg index d0df200..0095e16 100644 --- a/buildout.cfg +++ b/buildout.cfg @@ -20,6 +20,7 @@ eggs = recipe = zc.recipe.egg eggs = ${eggs:eggs} + unittest2 nose initialization = import os diff --git a/pyramid_formalchemy/__init__.py b/pyramid_formalchemy/__init__.py index 6e93ee0..abafd73 100644 --- a/pyramid_formalchemy/__init__.py +++ b/pyramid_formalchemy/__init__.py @@ -1,17 +1,29 @@ # -*- coding: utf-8 -*- from pyramid.httpexceptions import HTTPFound +from pyramid_formalchemy.resources import Models def includeme(config): """include formalchemy's zcml""" config.add_static_view('fa_admin', 'pyramid_formalchemy:static') config.add_directive('formalchemy_admin', 'pyramid_formalchemy.formalchemy_admin') + config.add_directive('formalchemy_model', 'pyramid_formalchemy.formalchemy_model') + +def formalchemy_model(config, route_name, + factory='pyramid_formalchemy.resources.ModelListing', + view='pyramid_formalchemy.views.ModelView', + package=None, model=None, forms=None, session_factory=None, **kwargs): + model = config.maybe_dotted(model) + return formalchemy_admin(config, route_name, factory=factory, view=view, package=package, + models=[model], model=model, forms=forms, session_factory=session_factory, **kwargs) def formalchemy_admin(config, route_name, factory='pyramid_formalchemy.resources.Models', view='pyramid_formalchemy.views.ModelView', - package=None, models=None, forms=None, session_factory=None): + package=None, models=None, forms=None, session_factory=None, **kwargs): """configure formalchemy's admin interface""" + route_name = route_name.strip('/') + kw = dict(route_name=route_name, view=view) if models: @@ -30,8 +42,9 @@ def formalchemy_admin(config, route_name, session_factory = config.maybe_dotted('%s.models.DBSession' % package) factory_args = { - '__models__': models, '__forms__': forms, + '__models__': models, + '__model_class__': kwargs.get('model'), '__session_factory__': session_factory, '__fa_route_name__': route_name, } @@ -41,19 +54,24 @@ def formalchemy_admin(config, route_name, factory = type('%s_%s' % (factory.__name__, route_name), (factory,), factory_args) def redirect(request): - return HTTPFound(location='%s/%s/' % (request.application_url, route_name)) + """redirect /route_name to /route_name/""" + matchdict = request.matchdict.copy() + url = request.route_url(route_name, traverse=(), **matchdict) + return HTTPFound(location=url) config.add_route('%s_redirect' % route_name, route_name, redirect) config.add_route(route_name, '%s/*traverse' % route_name, factory=factory) - config.add_view(context=factory, - renderer='pyramid_formalchemy:templates/admin/models.pt', - attr='models', - request_method='GET', - permission='view', - **kw) + if issubclass(factory, Models): + # don't want all models + config.add_view(context=factory, + renderer='pyramid_formalchemy:templates/admin/models.pt', + attr='models', + request_method='GET', + permission='view', + **kw) config.add_view(context='pyramid_formalchemy.resources.ModelListing', renderer='pyramid_formalchemy:templates/admin/listing.pt', diff --git a/pyramid_formalchemy/resources.py b/pyramid_formalchemy/resources.py index 1d728fd..e1ac2f7 100644 --- a/pyramid_formalchemy/resources.py +++ b/pyramid_formalchemy/resources.py @@ -13,14 +13,18 @@ class Base(object): if hasattr(self, '__fa_route_name__'): request.session_factory = self.__session_factory__ request.route_name = self.__fa_route_name__ - request.model = self.__models__ + request.models = self.__models__ request.forms = self.__forms__ request.fa_url = self.fa_url + request.model_instance = None request.model_class = None request.model_name = None request.model_id = None request.relation = None request.format = 'html' + if self.__model_class__: + request.model_class = self.__model_class__ + request.model_name = self.__model_class__.__name__ def get_model(self): request = self.request @@ -28,13 +32,13 @@ class Base(object): return request.model_class model_name = request.model_name model_class = None - if isinstance(request.model, list): - for model in request.model: + if isinstance(request.models, list): + for model in request.models: if model.__name__ == model_name: model_class = model break - elif hasattr(request.model, model_name): - model_class = getattr(request.model, model_name) + elif hasattr(request.models, model_name): + model_class = getattr(request.models, model_name) if model_class is None: raise NotFound() request.model_class = model_class @@ -45,6 +49,14 @@ class Base(object): session = self.request.session_factory() return session.query(model).get(self.request.model_id) + def _fa_url(self, *args): + matchdict = self.request.matchdict.copy() + if 'traverse' in matchdict: + del matchdict['traverse'] + return self.request.route_url(self.__fa_route_name__, + traverse=tuple([str(a) for a in args]), + **matchdict) + class Models(Base): @@ -53,8 +65,7 @@ class Models(Base): Base.__init__(self, request, None) def fa_url(self, *args): - return self.request.route_url(self.__fa_route_name__, - traverse='/'.join([str(a) for a in args])) + return self._fa_url(*args) def __getitem__(self, item): if item in ('json', 'xhr'): @@ -69,18 +80,21 @@ class Models(Base): class ModelListing(Base): - def __init__(self, request, name): + def __init__(self, request, name=None): Base.__init__(self, request, name) - request.model_name = name - model = self.get_model() + if name is None: + # request.model_class and request.model_name are already set + model = request.model_class + else: + request.model_name = name + model = self.get_model() if hasattr(model, '__acl__'): # get permissions from SA class self.__acl__ = model.__acl__ def fa_url(self, *args): - args = args[1:] - return self.request.route_url(self.__fa_route_name__, - traverse='/'.join([str(a) for a in args])) + return self._fa_url(*args[1:]) + def __getitem__(self, item): if item in ('json', 'xhr'): self.request.format = item @@ -94,11 +108,10 @@ class ModelListing(Base): class Model(Base): def fa_url(self, *args): - args = args[2:] - return self.request.route_url(self.__fa_route_name__, - traverse='/'.join([str(a) for a in args])) + return self._fa_url(*args[2:]) def __init__(self, request, name): Base.__init__(self, request, name) + request.model_instance = request.session_factory.query(request.model_class).get(name) request.model_id = name diff --git a/pyramid_formalchemy/templates/admin/edit.pt b/pyramid_formalchemy/templates/admin/edit.pt index b09fdc5..23faf45 100644 --- a/pyramid_formalchemy/templates/admin/edit.pt +++ b/pyramid_formalchemy/templates/admin/edit.pt @@ -4,7 +4,17 @@
\n \n') u"{'main': _callback_main}" _tmp = {'main': _callback_main, } u"main.macros['master']" diff --git a/pyramid_formalchemy/templates/admin/listing.pt b/pyramid_formalchemy/templates/admin/listing.pt index fcbe0bb..66f66dd 100644 --- a/pyramid_formalchemy/templates/admin/listing.pt +++ b/pyramid_formalchemy/templates/admin/listing.pt @@ -5,7 +5,7 @@+ tal:attributes="href request.fa_url(request.model_name, 'new')"> ${F_('New')} ${model_name} diff --git a/pyramid_formalchemy/templates/admin/listing.pt.py b/pyramid_formalchemy/templates/admin/listing.pt.py index 5b4234c..6a5a24a 100644 --- a/pyramid_formalchemy/templates/admin/listing.pt.py +++ b/pyramid_formalchemy/templates/admin/listing.pt.py @@ -4,15 +4,15 @@ def bind(): _lookup_attr = _loads('cchameleon.core.codegen\nlookup_attr\np1\n.') _init_scope = _loads('cchameleon.core.utils\necontext\np1\n.') _re_amp = _loads("cre\n_compile\np1\n(S'&(?!([A-Za-z]+|#[0-9]+);)'\np2\nI0\ntRp3\n.") - _attrs_4360530640 = _loads('(dp1\nVclass\np2\nVui-icon ui-icon-circle-plus\np3\ns.') - _attrs_4360530960 = _loads('(dp1\n.') - _attrs_4360531152 = _loads('(dp1\nVclass\np2\nVui-pager\np3\ns.') - _attrs_4360531728 = _loads('(dp1\nVclass\np2\nVui-widget-header ui-widget-link ui-corner-all\np3\ns.') + _attrs_4359083472 = _loads('(dp1\nVclass\np2\nVui-widget-header ui-widget-link ui-corner-all\np3\ns.') + _attrs_4359083344 = _loads('(dp1\n.') + _attrs_4359083216 = _loads('(dp1\nVclass\np2\nVui-pager\np3\ns.') _init_stream = _loads('cchameleon.core.generation\ninitialize_stream\np1\n.') - _attrs_4360531344 = _loads('(dp1\n.') + _attrs_4359083600 = _loads('(dp1\nVclass\np2\nVui-icon ui-icon-circle-plus\np3\ns.') + _attrs_4359083088 = _loads('(dp1\n.') _init_default = _loads('cchameleon.core.generation\ninitialize_default\np1\n.') _init_tal = _loads('cchameleon.core.generation\ninitialize_tal\np1\n.') - _attrs_4360531408 = _loads('(dp1\nVclass\np2\nVlayout-grid\np3\ns.') + _attrs_4359083280 = _loads('(dp1\nVclass\np2\nVlayout-grid\np3\ns.') def render(econtext, rcontext=None): macros = econtext.get('macros') _translate = econtext.get('_translate') @@ -33,13 +33,13 @@ def bind(): def _callback_main(econtext, _repeat, _out=_out, _write=_write, _domain=_domain, **_ignored): if _repeat: repeat.update(_repeat) - attrs = _attrs_4360530960 + attrs = _attrs_4359083088 u"''" _write(u'
\n ') - attrs = _attrs_4360531728 - u"request.route_url(request.route_name, traverse='%s/new' % request.model_name)" + attrs = _attrs_4359083472 + u"request.fa_url(request.model_name, 'new')" _write(u'\n ') - attrs = _attrs_4360530640 + attrs = _attrs_4359083600 u"F_('New')" _write(u'\n ') _tmp1 = econtext['F_']('New') diff --git a/pyramid_formalchemy/templates/admin/master.pt b/pyramid_formalchemy/templates/admin/master.pt index 2200071..f0d5d49 100644 --- a/pyramid_formalchemy/templates/admin/master.pt +++ b/pyramid_formalchemy/templates/admin/master.pt @@ -20,15 +20,3 @@