diff --git a/edbob/pyramid/forms/formalchemy/__init__.py b/edbob/pyramid/forms/formalchemy/__init__.py index c0a35ef..6ab93d5 100644 --- a/edbob/pyramid/forms/formalchemy/__init__.py +++ b/edbob/pyramid/forms/formalchemy/__init__.py @@ -29,7 +29,6 @@ from __future__ import absolute_import import datetime -import new from pyramid.renderers import render from webhelpers.html.tags import literal @@ -38,7 +37,6 @@ import formalchemy from formalchemy.validators import accepts_none from edbob.lib import pretty -from edbob.pyramid import Session, helpers from edbob.time import localize from edbob.pyramid.forms.formalchemy.fieldset import * @@ -49,7 +47,7 @@ from edbob.pyramid.forms.formalchemy.renderers import * __all__ = ['ChildGridField', 'PropertyField', 'EnumFieldRenderer', 'PrettyDateTimeFieldRenderer', 'AutocompleteFieldRenderer', 'FieldSet', 'make_fieldset', 'required', 'pretty_datetime', - 'AssociationProxyField'] + 'AssociationProxyField', 'YesNoFieldRenderer'] class TemplateEngine(formalchemy.templates.TemplateEngine): @@ -118,13 +116,14 @@ def pretty_datetime(value, from_='local', to='local'): pretty.date(value))) -class PrettyDateTimeFieldRenderer(formalchemy.fields.DateTimeFieldRenderer): - """ - Adds "pretty" date/time support for FormAlchemy. - """ +def PrettyDateTimeFieldRenderer(from_='local', to='local'): - def render_readonly(self, **kwargs): - return pretty_datetime(self.raw_value) + class PrettyDateTimeFieldRenderer(formalchemy.fields.DateTimeFieldRenderer): + + def render_readonly(self, **kwargs): + return pretty_datetime(self.raw_value, from_=from_, to=to) + + return PrettyDateTimeFieldRenderer class DateTimeFieldRenderer(formalchemy.fields.DateTimeFieldRenderer): @@ -142,58 +141,3 @@ class DateTimeFieldRenderer(formalchemy.fields.DateTimeFieldRenderer): return '' FieldSet.default_renderers[formalchemy.types.DateTime] = DateTimeFieldRenderer - - -def AutocompleteFieldRenderer(service_url, display, width='300px', callback=None, **kwargs): - """ - Returns a field renderer class which leverages jQuery autocomplete to - provide a more user-friendly experience. This is typically used in place - of a ``SelectFieldRenderer`` when the data set is deemed too large for that - renderer. - - ``service_url`` is required and will ultimately be passed to the - ``jQuery.autocomplete()`` function via the ``serviceUrl`` data parameter. - - ``display`` must be either a callable which accepts an object key as its - only positional argument, or else a tuple of the form ``(Class, 'attr')``. - - ``width`` is optional but is also passed to the jQuery function. - - If ``callback`` is specified, it should be the name of a JavaScript - function within the containing page's scope. This is used in place of - event handlers for autocomplete fields. - """ - - kwargs['service_url'] = service_url - kwargs['width'] = width - kwargs['callback'] = callback - Renderer = new.classobj('AutocompleteFieldRenderer', (_AutocompleteFieldRenderer,), kwargs) - if callable(display): - Renderer.display = classmethod(display) - else: - Renderer.display = display - return Renderer - - -class _AutocompleteFieldRenderer(formalchemy.fields.FieldRenderer): - """ - Implementation for :class:`AutocompleteFieldRenderer` class. - """ - - def _display(self, value): - if callable(self.display): - return self.display(value) - if not value: - return '' - obj = Session.query(self.display[0]).get(value) - if not obj: - return '' - return getattr(obj, self.display[1]) - - def render(self, **kwargs): - autocompleter_name = 'autocompleter_%s' % self.name.replace('-', '_') - return formalchemy.config.engine('field_autocomplete', fieldname=self.name, - fieldvalue=self.value, display=self._display(self.value), - autocompleter=autocompleter_name, - service_url=self.service_url, width=self.width, - callback=self.callback, h=helpers, **kwargs) diff --git a/edbob/pyramid/forms/formalchemy/renderers.py b/edbob/pyramid/forms/formalchemy/renderers.py index c2e21f3..783d323 100644 --- a/edbob/pyramid/forms/formalchemy/renderers.py +++ b/edbob/pyramid/forms/formalchemy/renderers.py @@ -28,8 +28,33 @@ import formalchemy +from pyramid.renderers import render -__all__ = ['EnumFieldRenderer'] + +__all__ = ['AutocompleteFieldRenderer', 'EnumFieldRenderer', + 'YesNoFieldRenderer'] + + +def AutocompleteFieldRenderer(service_url, width='300px'): + """ + Autocomplete renderer. + """ + + class AutocompleteFieldRenderer(formalchemy.fields.FieldRenderer): + + @property + def focus_name(self): + return self.name + '-textbox' + + def render(self, **kwargs): + kwargs.setdefault('field_name', self.name) + kwargs.setdefault('field_value', self.value) + kwargs.setdefault('field_display', self.raw_value) + kwargs.setdefault('service_url', service_url) + kwargs.setdefault('width', width) + return render('/forms/field_autocomplete.mako', kwargs) + + return AutocompleteFieldRenderer def EnumFieldRenderer(enum): @@ -54,3 +79,12 @@ def EnumFieldRenderer(enum): return formalchemy.fields.SelectFieldRenderer.render(self, opts, **kwargs) return Renderer + + +class YesNoFieldRenderer(formalchemy.fields.CheckBoxFieldRenderer): + + def render_readonly(self, **kwargs): + value = self.raw_value + if value is None: + return '' + return 'Yes' if value else 'No' diff --git a/edbob/pyramid/templates/autocomplete.mako b/edbob/pyramid/templates/autocomplete.mako index 7b09755..3c1dcb2 100644 --- a/edbob/pyramid/templates/autocomplete.mako +++ b/edbob/pyramid/templates/autocomplete.mako @@ -1,16 +1,16 @@ -<%def name="autocomplete(field_name, field_value, field_display, service_url, width='300px', callback=None)"> +<%def name="autocomplete(field_name, service_url, field_value=None, field_display=None, width='300px', callback=None)">