diff --git a/edbob/db/__init__.py b/edbob/db/__init__.py index 6bd6549..e19e88f 100644 --- a/edbob/db/__init__.py +++ b/edbob/db/__init__.py @@ -28,6 +28,7 @@ from sqlalchemy import engine_from_config, MetaData from sqlalchemy.orm import sessionmaker +from sqlalchemy.ext.declarative import declarative_base import edbob @@ -41,6 +42,7 @@ inited = False engines = None engine = None Session = sessionmaker() +Base = declarative_base() # metadata = None @@ -70,7 +72,6 @@ def init(config): # from edbob.db import classes from edbob.db import model from edbob.db import enum - from edbob.db.model import Base # from edbob.db.model import get_metadata # from edbob.db.mappers import make_mappers # from edbob.db.extensions import extend_framework @@ -98,7 +99,6 @@ def init(config): engine = engines.get('default') if engine: - Session.configure(bind=engine) Base.metadata.bind = engine # metadata = get_metadata(bind=engine) diff --git a/edbob/db/model.py b/edbob/db/model.py index bc5a4a3..2e3e6de 100644 --- a/edbob/db/model.py +++ b/edbob/db/model.py @@ -27,16 +27,14 @@ """ from sqlalchemy import Column, String, Text -from sqlalchemy.ext.declarative import declarative_base import edbob # from edbob import Object, get_uuid +from edbob.db import Base __all__ = ['ActiveExtension', 'Setting'] -Base = declarative_base() - # class ClassWithUuid(Object): # """ diff --git a/edbob/pyramid/filters.py b/edbob/pyramid/filters.py index 5e3d93e..a57820c 100644 --- a/edbob/pyramid/filters.py +++ b/edbob/pyramid/filters.py @@ -182,11 +182,12 @@ def get_search_config(name, request, filter_map, **kwargs): """ config = {} - for field in filter_map: - config['include_filter_'+field] = False - config.update(kwargs) def update_config(dict_, prefix='', exclude_by_default=False): + """ + Updates the ``config`` dictionary based on the contents of ``dict_``. + """ + for field in filter_map: if prefix+'include_filter_'+field in dict_: include = dict_[prefix+'include_filter_'+field] @@ -199,12 +200,25 @@ def get_search_config(name, request, filter_map, **kwargs): if prefix+field in dict_: config[field] = dict_[prefix+field] + # Update config to exclude all filters by default. + for field in filter_map: + config['include_filter_'+field] = False + + # Update config with defaults from ``kwargs``. + config.update(kwargs) + + # Update config with data cached in Beaker session. update_config(request.session, prefix=name+'.') + + # Update config with data from GET/POST request. if request.params.get('filters'): update_config(request.params, exclude_by_default=True) + + # Cache filter data in Beaker session. for key in config: if not key.startswith('filter_factory_'): request.session[name+'.'+key] = config[key] + config['request'] = request config['filter_map'] = filter_map return config diff --git a/edbob/pyramid/forms/formalchemy.py b/edbob/pyramid/forms/formalchemy.py index b27b6f2..49f9a1c 100644 --- a/edbob/pyramid/forms/formalchemy.py +++ b/edbob/pyramid/forms/formalchemy.py @@ -44,8 +44,9 @@ from edbob.util import prettify from edbob.pyramid import Session -__all__ = ['AlchemyGrid', 'EnumFieldRenderer', 'PrettyDateTimeFieldRenderer', - 'make_fieldset', 'required'] +__all__ = ['AlchemyGrid', 'ChildGridField', 'EnumFieldRenderer', + 'PrettyDateTimeFieldRenderer', 'make_fieldset', 'required', + 'pretty_datetime'] class TemplateEngine(formalchemy.templates.TemplateEngine): @@ -142,10 +143,10 @@ class AlchemyGrid(formalchemy.Grid): return field.render() def row_attrs(self, i): - return format_attrs( - uuid=self.model.uuid, - class_='even' if i % 2 else 'odd', - ) + attrs = dict(class_='even' if i % 2 else 'odd') + if hasattr(self.model, 'uuid'): + attrs['uuid'] = self.model.uuid + return format_attrs(**attrs) def url_attrs(self): return format_attrs(url=self.url_grid, @@ -265,6 +266,18 @@ class AlchemyGrid(formalchemy.Grid): # return '' +class ChildGridField(formalchemy.Field): + """ + Convenience class for including a child grid within a fieldset as a + read-only field. + """ + + def __init__(self, name, value, *args, **kwargs): + super(ChildGridField, self).__init__(name, *args, **kwargs) + self.set(value=value) + self.set(readonly=True) + + def make_fieldset(model, **kwargs): kwargs.setdefault('session', Session()) return FieldSet(model, **kwargs) diff --git a/edbob/pyramid/grids.py b/edbob/pyramid/grids.py index fa70cc0..d948f80 100644 --- a/edbob/pyramid/grids.py +++ b/edbob/pyramid/grids.py @@ -29,6 +29,7 @@ from collections import OrderedDict from sqlalchemy.orm import Query +from sqlalchemy.orm.attributes import InstrumentedAttribute from pyramid.renderers import render from pyramid.response import Response @@ -151,12 +152,19 @@ def get_pager(query, config): ) -def get_sort_map(cls, names, **kwargs): +def get_sort_map(cls, names=None, **kwargs): """ Convenience function which returns a sort map. """ smap = {} + if names is None: + names = [] + for attr in cls.__dict__: + obj = getattr(cls, attr) + if isinstance(obj, InstrumentedAttribute): + if obj.key != 'uuid': + names.append(obj.key) for name in names: smap[name] = sorter(getattr(cls, name)) smap.update(kwargs) diff --git a/edbob/pyramid/static/css/edbob.css b/edbob/pyramid/static/css/edbob.css index 744d430..c0b6261 100644 --- a/edbob/pyramid/static/css/edbob.css +++ b/edbob/pyramid/static/css/edbob.css @@ -257,7 +257,8 @@ div.grid table { border-top: 1px solid black; border-left: 1px solid black; border-collapse: collapse; - font-size: 90%; + font-size: 9pt; + line-height: normal; white-space: nowrap; width: 100%; } @@ -356,7 +357,8 @@ div.pager p.page-links { div.field-couple { clear: both; - margin-bottom: 10px; + overflow: auto; + min-height: 30px; } div.field-couple div.label, diff --git a/edbob/pyramid/static/js/edbob.js b/edbob/pyramid/static/js/edbob.js index b238410..c0bee70 100644 --- a/edbob/pyramid/static/js/edbob.js +++ b/edbob/pyramid/static/js/edbob.js @@ -165,10 +165,11 @@ $(function() { div.find('button[type=reset]').show(); }); - $('div.filters form').live('submit', function() { - var div = $(this).parents('table.search-wrapper').next(); + $('div.filterset form').live('submit', function() { + var div = $('div.grid:first'); + var data = $(this).serialize() + '&partial=true'; loading(div); - $.post(div.attr('url'), $(this).serialize(), function(data) { + $.post(div.attr('url'), data, function(data) { div.replaceWith(data); }); return false; diff --git a/edbob/pyramid/templates/edbob/base.mako b/edbob/pyramid/templates/edbob/base.mako index 5a09414..4882d2d 100644 --- a/edbob/pyramid/templates/edbob/base.mako +++ b/edbob/pyramid/templates/edbob/base.mako @@ -49,11 +49,13 @@ ## % endfor ## ## % endif -##
-## %for message in request.session.pop_flash(): -##
${message}
-## %endfor -##
+ % if request.session.peek_flash(): +
+ % for msg in request.session.pop_flash(): +
${msg|n}
+ % endfor +
+ % endif ${self.body()} diff --git a/edbob/pyramid/templates/forms/filterset.mako b/edbob/pyramid/templates/forms/filterset.mako index 8ae1814..e0f0215 100644 --- a/edbob/pyramid/templates/forms/filterset.mako +++ b/edbob/pyramid/templates/forms/filterset.mako @@ -1,5 +1,6 @@
${search.begin()} + ${search.hidden('filters', True)} <% visible = [] %> % for f in search.sorted_filters(): <% f = search.filters[f] %> diff --git a/edbob/pyramid/views/crud.py b/edbob/pyramid/views/crud.py index d0e12c9..01d3240 100644 --- a/edbob/pyramid/views/crud.py +++ b/edbob/pyramid/views/crud.py @@ -105,7 +105,6 @@ def crud(request, cls, fieldset_factory, home=None, delete=None, post_sync=None, # return HTTPFound(location=self.request.route_url(objects, action='index')) if not fs.readonly and request.POST: - # print self.request.POST fs.rebind(data=request.params) if fs.validate(): with transaction.manager: