From 261f722ccd24ef46f567718fa0ab50dc2d0e8553 Mon Sep 17 00:00:00 2001 From: Gael Pasgrimaud Date: Mon, 2 May 2011 22:57:17 +0200 Subject: [PATCH] add config.formalchemy_model() --- buildout.cfg | 1 + pyramid_formalchemy/__init__.py | 36 +++- pyramid_formalchemy/resources.py | 45 +++-- pyramid_formalchemy/templates/admin/edit.pt | 12 +- .../templates/admin/edit.pt.py | 116 ++++++++++-- .../templates/admin/listing.pt | 2 +- .../templates/admin/listing.pt.py | 28 +-- pyramid_formalchemy/templates/admin/master.pt | 12 -- .../templates/admin/master.pt.py | 166 +++--------------- pyramid_formalchemy/templates/admin/new.pt | 4 +- pyramid_formalchemy/templates/admin/new.pt.py | 40 ++--- pyramid_formalchemy/templates/admin/show.pt | 13 +- .../templates/admin/show.pt.py | 129 ++++++++++++-- pyramid_formalchemy/views.py | 43 ++--- pyramidapp/jquery.ini | 2 +- pyramidapp/pyramidapp/__init__.py | 5 + pyramidapp/pyramidapp/jquery.py | 9 +- pyramidapp/pyramidapp/tests.py | 70 +++++++- pyramidapp/security.ini | 2 +- pyramidapp/test.ini | 2 +- 20 files changed, 447 insertions(+), 290 deletions(-) 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 @@
-
+
+

+ + + + + + ${F_('Cancel')} + +

diff --git a/pyramid_formalchemy/templates/admin/edit.pt.py b/pyramid_formalchemy/templates/admin/edit.pt.py index 1877e38..b1843d5 100644 --- a/pyramid_formalchemy/templates/admin/edit.pt.py +++ b/pyramid_formalchemy/templates/admin/edit.pt.py @@ -3,13 +3,20 @@ def bind(): from cPickle import loads as _loads _lookup_attr = _loads('cchameleon.core.codegen\nlookup_attr\np1\n.') _init_scope = _loads('cchameleon.core.utils\necontext\np1\n.') - _attrs_4360507280 = _loads('(dp1\nVaction\np2\nV\nsVmethod\np3\nVPOST\np4\nsVenctype\np5\nVmultipart/form-data\np6\ns.') - _attrs_4360506064 = _loads('(dp1\nVname\np2\nV_method\np3\nsVtype\np4\nVhidden\np5\nsVvalue\np6\nVPUT\np7\ns.') + _re_amp = _loads("cre\n_compile\np1\n(S'&(?!([A-Za-z]+|#[0-9]+);)'\np2\nI0\ntRp3\n.") + _attrs_4359005584 = _loads('(dp1\n.') + _attrs_4359005840 = _loads('(dp1\nVname\np2\nV_method\np3\nsVtype\np4\nVhidden\np5\nsVvalue\np6\nVPUT\np7\ns.') + _attrs_4359006416 = _loads('(dp1\nVclass\np2\nVfa_field\np3\ns.') + _attrs_4359006672 = _loads('(dp1\nVclass\np2\nVui-widget-header ui-widget-link ui-corner-all\np3\ns.') + _attrs_4359005008 = _loads('(dp1\nVclass\np2\nVui-icon ui-icon-circle-arrow-w\np3\ns.') _init_stream = _loads('cchameleon.core.generation\ninitialize_stream\np1\n.') - _init_tal = _loads('cchameleon.core.generation\ninitialize_tal\np1\n.') + _attrs_4359005968 = _loads('(dp1\n.') _init_default = _loads('cchameleon.core.generation\ninitialize_default\np1\n.') - _attrs_4360507216 = _loads('(dp1\n.') - _attrs_4360719504 = _loads('(dp1\n.') + _attrs_4359006544 = _loads('(dp1\nVhref\np2\nV#\nsVclass\np3\nVui-widget-header ui-widget-link ui-widget-button ui-corner-all\np4\ns.') + _attrs_4359005520 = _loads('(dp1\nVaction\np2\nV\nsVmethod\np3\nVPOST\np4\nsVenctype\np5\nVmultipart/form-data\np6\ns.') + _attrs_4359006736 = _loads("(dp1\nVtype\np2\nVsubmit\np3\nsVvalue\np4\nV${F_('Save')}\np5\ns.") + _attrs_4359005776 = _loads('(dp1\n.') + _init_tal = _loads('cchameleon.core.generation\ninitialize_tal\np1\n.') def render(econtext, rcontext=None): macros = econtext.get('macros') _translate = econtext.get('_translate') @@ -30,15 +37,15 @@ def bind(): def _callback_main(econtext, _repeat, _out=_out, _write=_write, _domain=_domain, **_ignored): if _repeat: repeat.update(_repeat) - attrs = _attrs_4360719504 + attrs = _attrs_4359005584 _write(u'
\n ') - attrs = _attrs_4360507280 + attrs = _attrs_4359005520 u"''" _write(u'
\n ') _default.value = default = '' u'fs.render()' _content = _lookup_attr(econtext['fs'], 'render')() - attrs = _attrs_4360507216 + attrs = _attrs_4359005776 u'_content' _write(u'
') _tmp1 = _content @@ -57,15 +64,92 @@ def bind(): _tmp = str(_tmp) _write(_tmp) _write(u'
\n ') - attrs = _attrs_4360506064 - u"main.macros['buttons']" + attrs = _attrs_4359005840 _write(u'\n ') - _metal = _lookup_attr(econtext['main'], 'macros')['buttons'] - u'{}' - _tmp = {} - u"main.macros['buttons']" - _metal.render(_tmp, _out=_out, _write=_write, _domain=_domain, econtext=econtext) - _write(u'\n
\n
\n') + attrs = _attrs_4359005968 + _write(u'
\n ') + attrs = _attrs_4359006416 + _write(u'

\n ') + attrs = _attrs_4359006544 + _write(u'\n ') + attrs = _attrs_4359006736 + 'join(value("F_(\'Save\')"),)' + _write(u'' in _tmp1): + _tmp1 = _tmp1.replace('>', '>') + if ('"' in _tmp1): + _tmp1 = _tmp1.replace('"', '"') + _write(((' value="' + _tmp1) + '"')) + _write(u' />\n \n ') + attrs = _attrs_4359006672 + u'request.fa_url(request.model_name)' + _write(u'' in _tmp1): + _tmp1 = _tmp1.replace('>', '>') + if ('"' in _tmp1): + _tmp1 = _tmp1.replace('"', '"') + _write(((' href="' + _tmp1) + '"')) + _write(u'>\n ') + attrs = _attrs_4359005008 + u"F_('Cancel')" + _write(u'\n ') + _tmp1 = econtext['F_']('Cancel') + _tmp = _tmp1 + if (_tmp.__class__ not in (str, unicode, int, float, )): + try: + _tmp = _tmp.__html__ + except: + _tmp = _translate(_tmp, domain=_domain, mapping=None, target_language=target_language, default=None) + else: + _tmp = _tmp() + _write(_tmp) + _tmp = None + if (_tmp is not None): + if not isinstance(_tmp, unicode): + _tmp = str(_tmp) + if ('&' in _tmp): + if (';' in _tmp): + _tmp = _re_amp.sub('&', _tmp) + else: + _tmp = _tmp.replace('&', '&') + if ('<' in _tmp): + _tmp = _tmp.replace('<', '<') + if ('>' in _tmp): + _tmp = _tmp.replace('>', '>') + _write(_tmp) + _write(u'\n \n

\n
\n \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 ') _default.value = default = '' u'pager' _content = econtext['pager'] - attrs = _attrs_4360531152 + attrs = _attrs_4359083216 u'_content' _write(u'
') _tmp1 = _content @@ -62,7 +62,7 @@ def bind(): _default.value = default = '' u'fs.render()' _content = _lookup_attr(econtext['fs'], 'render')() - attrs = _attrs_4360531408 + attrs = _attrs_4359083280 u'_content' _write(u'
') _tmp1 = _content @@ -81,12 +81,12 @@ def bind(): _tmp = str(_tmp) _write(_tmp) _write(u'
\n ') - attrs = _attrs_4360531344 + attrs = _attrs_4359083344 _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 @@ -

-

- - - - - - ${F_('Cancel')} - -

-
diff --git a/pyramid_formalchemy/templates/admin/master.pt.py b/pyramid_formalchemy/templates/admin/master.pt.py index 603a181..37543a5 100644 --- a/pyramid_formalchemy/templates/admin/master.pt.py +++ b/pyramid_formalchemy/templates/admin/master.pt.py @@ -1,24 +1,24 @@ registry = dict(version=0) def bind(): from cPickle import loads as _loads - _attrs_4356111248 = _loads('(dp1\nVrel\np2\nVstylesheet\np3\ns.') _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_4356112272 = _loads('(dp1\n.') - _attrs_4356111632 = _loads('(dp1\nVid\np2\nVheader\np3\nsVclass\np4\nVui-widget-header ui-corner-all\np5\ns.') - _attrs_4356108816 = _loads('(dp1\n.') - _attrs_4356111440 = _loads('(dp1\n.') + _attrs_4358968400 = _loads('(dp1\n.') + _attrs_4358849552 = _loads('(dp1\n.') + _attrs_4358967760 = _loads('(dp1\nVid\np2\nVheader\np3\nsVclass\np4\nVui-widget-header ui-corner-all\np5\ns.') + _attrs_4358720592 = _loads('(dp1\nVrel\np2\nVstylesheet\np3\ns.') + _attrs_4358967504 = _loads('(dp1\nVid\np2\nVcontent\np3\nsVclass\np4\nVui-admin ui-widget\np5\ns.') + _attrs_4358967888 = _loads('(dp1\nVclass\np2\nVbreadcrumb\np3\ns.') _init_stream = _loads('cchameleon.core.generation\ninitialize_stream\np1\n.') - _attrs_4356108496 = _loads('(dp1\n.') - _attrs_4356112144 = _loads('(dp1\nVclass\np2\nVbreadcrumb\np3\ns.') - _attrs_4356111184 = _loads('(dp1\n.') - _attrs_4356111888 = _loads('(dp1\nVid\np2\nVcontent\np3\nsVclass\np4\nVui-admin ui-widget\np5\ns.') + _attrs_4358968272 = _loads('(dp1\n.') + _attrs_4358721104 = _loads('(dp1\n.') + _attrs_4358721040 = _loads('(dp1\n.') _init_default = _loads('cchameleon.core.generation\ninitialize_default\np1\n.') - _attrs_4356111120 = _loads('(dp1\n.') - _attrs_4356112080 = _loads('(dp1\n.') + _attrs_4358721232 = _loads('(dp1\n.') + _attrs_4358967696 = _loads('(dp1\n.') _init_tal = _loads('cchameleon.core.generation\ninitialize_tal\np1\n.') - _attrs_4356111056 = _loads('(dp1\n.') + _attrs_4358967952 = _loads('(dp1\n.') def render(econtext, rcontext=None): macros = econtext.get('macros') _translate = econtext.get('_translate') @@ -34,15 +34,15 @@ def bind(): default = None u'None' _domain = None - attrs = _attrs_4356111440 + attrs = _attrs_4358849552 _write(u'\n ') - attrs = _attrs_4356111056 + attrs = _attrs_4358721040 u"''" _write(u'\n ') _default.value = default = '' u"request.model_name or 'root'" _content = (_lookup_attr(econtext['request'], 'model_name') or 'root') - attrs = _attrs_4356111184 + attrs = _attrs_4358721104 u'_content' _write(u'') _tmp1 = _content @@ -70,7 +70,7 @@ def bind(): _tmp = _tmp.replace('>', '>') _write(_tmp) _write(u'\n ') - attrs = _attrs_4356111248 + attrs = _attrs_4358720592 u"request.static_url('pyramid_formalchemy:static/admin.css')" _write(u'\n \n ') - attrs = _attrs_4356111120 + attrs = _attrs_4358721232 _write(u'\n ') - attrs = _attrs_4356111888 + attrs = _attrs_4358967504 _write(u'
\n ') - attrs = _attrs_4356111632 + attrs = _attrs_4358967760 _write(u'

\n ') - attrs = _attrs_4356112144 + attrs = _attrs_4358967888 u'breadcrumb' _write(u'