:mod:`formalchemy.tables` -- `Grid`: Rendering collections ========================================================== .. automodule:: formalchemy.tables Besides :class:`~formalchemy.forms.FieldSet`, `FormAlchemy` provides `Grid` for editing and rendering multiple instances at once. Most of what you know about :class:`~formalchemy.forms.FieldSet` applies to `Grid`, with the following differences to accomodate being bound to multiple objects: The Grid class -------------- .. autoclass:: Grid :members: Creating -------- The `Grid` constructor takes parameters (`cls`, `instances=[]`, `session=None`, `data=None`). A significant difference from :class:`~formalchemy.forms.FieldSet` is that the first argument must _always_ be a mapped class, e.g., `User`. `instances` is the objects to render, which must all be of the given type. The other parameters are the same as in :class:`~formalchemy.forms.FieldSet`. Binding ------- `Grid` `bind` and `rebind` methods are similar to those methods in :class:`~formalchemy.forms.FieldSet`, except they take an iterable `instances` instead of an instance `model`. Thus, the full signature is (`instances`, `session=None`, `data=None`). Configuration ------------- The `Grid` `configure` method takes the same arguments as :class:`~formalchemy.forms.FieldSet` (`pk`, `exclude`, `include`, `options`, `readonly`), except there is no `focus` argument. Validation and Sync ------------------- These are the same as in :class:`~formalchemy.forms.FieldSet`, except that you can also call `sync_one(instance)` to sync a single one of the instances that are bound to the `Grid`. The `Grid` `errors` attribute is a dictionary keyed by bound instance, whose value is similar to the `errors` from a :class:`~formalchemy.forms.FieldSet`, that is, a dictionary whose keys are `Field`s, and whose values are `ValidationError` instances. Customizing Grid ---------------- Overriding `Grid` rendering is similar to :class:`~formalchemy.forms.FieldSet`. The differences are: * The default templates take a `collection` parameter instead of `fieldset`, which is the instance of `Grid` to render * The instances given to the collection are available by iterating the collection (`for row in collection`). Alternately, you can call `_set_active(row)`. The default templates are `formalchemy.tables.template_grid_readonly` and `formalchemy.tables.template_grid`. Usage ----- You need some imports:: >>> from formalchemy.tables import * .. Hidden code needed for testing >>> from formalchemy.tests import * Then you can initialize a `Grid` and bind it to a list of row instance:: >>> tc = Grid(User, [bill]) >>> tc.configure(readonly=True) This will render instances as an html table:: >>> print(tc.render()) Email Password Name Orders bill@example.com 1234 Bill Quantity: 10 You can also add a field to the `Grid` manually:: >>> from formalchemy.helpers import literal >>> tc2 = Grid(User, [bill, john]) >>> tc2.append(Field('link', type=types.String, value=lambda item: literal('link') % item.id)) >>> tc2.configure(readonly=True) >>> print(tc2.render()) Email Password Name Orders Link bill@example.com 1234 Bill Quantity: 10 link john@example.com 5678 John Quantity: 5, Quantity: 6 link You can provide a dict as new values:: >>> g = Grid(User, [bill, john], data={'User-1-email': 'bill_@example.com', 'User-1-password': '1234_', 'User-1-name': 'Bill_', 'User-1-orders': '1', 'User-2-email': 'john_@example.com', 'User-2-password': '5678_', 'User-2-name': 'John_', 'User-2-orders': ['2', '3'], }) Validation work like `Fieldset`:: >>> g.validate() True Sync too: >>> g.sync() >>> session.flush() >>> session.refresh(john) >>> john.email == 'john_@example.com' True >>> session.rollback()