3
0
Fork 0

fix: add way to set field widgets using pseudo-type

more to come on this idea hopefully..i think it's a good pattern?
This commit is contained in:
Lance Edgar 2024-12-11 23:05:25 -06:00
parent bf8397ba23
commit eda2326a97
3 changed files with 63 additions and 5 deletions

View file

@ -457,23 +457,62 @@ class Form:
if self.schema: if self.schema:
self.schema[key] = node self.schema[key] = node
def set_widget(self, key, widget): def set_widget(self, key, widget, **kwargs):
""" """
Set/override the widget for a field. Set/override the widget for a field.
You can specify a widget instance or else a named "type" of
widget, in which case that is passed along to
:meth:`make_widget()`.
:param key: Name of field. :param key: Name of field.
:param widget: Instance of :param widget: Either a :class:`deform:deform.widget.Widget`
:class:`deform:deform.widget.Widget`. instance, or else a widget "type" name.
:param \**kwargs: Any remaining kwargs are passed along to
:meth:`make_widget()` - if applicable.
Widget overrides are tracked via :attr:`widgets`. Widget overrides are tracked via :attr:`widgets`.
""" """
if not isinstance(widget, deform.widget.Widget):
widget_obj = self.make_widget(widget, **kwargs)
if not widget_obj:
raise ValueError(f"widget type not supported: {widget}")
widget = widget_obj
self.widgets[key] = widget self.widgets[key] = widget
# update schema if necessary # update schema if necessary
if self.schema and key in self.schema: if self.schema and key in self.schema:
self.schema[key].widget = widget self.schema[key].widget = widget
def make_widget(self, widget_type, **kwargs):
"""
Make and return a new field widget of the given type.
This has built-in support for the following types (although
subclass can override as needed):
* ``'notes'`` => :class:`~wuttaweb.forms.widgets.NotesWidget`
See also :meth:`set_widget()` which may call this method
automatically.
:param widget_type: Which of the above (or custom) widget
type to create.
:param \**kwargs: Remaining kwargs are passed as-is to the
widget factory.
:returns: New widget instance, or ``None`` if e.g. it could
not determine how to create the widget.
"""
from wuttaweb.forms import widgets
if widget_type == 'notes':
return widgets.NotesWidget(**kwargs)
def set_grid(self, key, grid): def set_grid(self, key, grid):
""" """
Establish a :term:`grid` to be displayed for a field. This Establish a :term:`grid` to be displayed for a field. This

View file

@ -34,7 +34,6 @@ from sqlalchemy import orm
from wuttjamaican.db.model import Upgrade from wuttjamaican.db.model import Upgrade
from wuttaweb.views import MasterView from wuttaweb.views import MasterView
from wuttaweb.forms import widgets
from wuttaweb.forms.schema import UserRef, WuttaEnum, FileDownload from wuttaweb.forms.schema import UserRef, WuttaEnum, FileDownload
from wuttaweb.progress import get_progress_session from wuttaweb.progress import get_progress_session
@ -147,7 +146,7 @@ class UpgradeView(MasterView):
f.set_node('created_by', UserRef(self.request)) f.set_node('created_by', UserRef(self.request))
# notes # notes
f.set_widget('notes', widgets.NotesWidget()) f.set_widget('notes', 'notes')
# status # status
if self.creating: if self.creating:

View file

@ -142,6 +142,26 @@ class TestForm(TestCase):
self.assertIs(form.widgets['foo'], new_widget) self.assertIs(form.widgets['foo'], new_widget)
self.assertIs(schema['foo'].widget, new_widget) self.assertIs(schema['foo'].widget, new_widget)
# can also just specify widget pseudo-type (invalid)
self.assertNotIn('bar', form.widgets)
self.assertRaises(ValueError, form.set_widget, 'bar', 'ldjfadjfadj')
# can also just specify widget pseudo-type (valid)
self.assertNotIn('bar', form.widgets)
form.set_widget('bar', 'notes')
self.assertIsInstance(form.widgets['bar'], widgets.NotesWidget)
def test_make_widget(self):
form = self.make_form(fields=['foo', 'bar'])
# notes
widget = form.make_widget('notes')
self.assertIsInstance(widget, widgets.NotesWidget)
# invalid
widget = form.make_widget('fdajvdafjjf')
self.assertIsNone(widget)
def test_set_grid(self): def test_set_grid(self):
form = self.make_form(fields=['foo', 'bar']) form = self.make_form(fields=['foo', 'bar'])
self.assertNotIn('foo', form.widgets) self.assertNotIn('foo', form.widgets)