formalchemy.fieldsFields and Renderers

Fields

class formalchemy.fields.AbstractField(parent)

Contains the information necessary to render (and modify the rendering of) a form field

Methods taking an options parameter will accept several ways of specifying those options:

  • an iterable of SQLAlchemy objects; str() of each object will be the description, and the primary key the value
  • a SQLAlchemy query; the query will be executed with all() and the objects returned evaluated as above
  • an iterable of (description, value) pairs
  • a dictionary of {description: value} pairs

Options can be “chained” indefinitely because each modification returns a new Field instance, so you can write:

>>> from formalchemy.tests import FieldSet, User
>>> fs = FieldSet(User)
>>> fs.append(Field('foo').dropdown(options=[('one', 1), ('two', 2)]).radio())

or:

>>> fs.configure(options=[fs.name.label('Username').readonly()])
bind(parent)
Return a copy of this Field, bound to a different parent
checkbox(options=None)
Render the field as a set of checkboxes.
dropdown(options=None, multiple=False, size=5)
Render the field as an HTML select field. (With the multiple option this is not really a ‘dropdown’.)
hidden()
Render the field hidden. (Value only, no label.)
is_readonly()
True iff this Field is in readonly mode
is_required()
True iff this Field must be given a non-empty value
label(text)
Change the label associated with this field. By default, the field name is used, modified for readability (e.g., ‘user_name’ -> ‘User name’).
model_value
raw value from model, transformed if necessary for use as a form input value.
password()
Render the field as a password input, hiding its value.
query(*args, **kwargs)
Perform a query in the parent’s session
radio(options=None)
Render the field as a set of radio buttons.
raw_value()
raw value from model. different from .model_value in SQLAlchemy fields, because for reference types, .model_value will return the foreign key ID. This will return the actual object referenced instead.
readonly(value=True)
Render the field readonly.
render()
Render this Field as HTML.
render_readonly()
Render this Field as HTML for read only mode.
required()
Convenience method for validate(validators.required). By default, NOT NULL columns are required. You can only add required-ness, not remove it.
reset()
Return the field with all configuration changes reverted.
set(**kwattrs)

Update field attributes in place. Allowed attributes are: validate, renderer, required, readonly, nul_as, label, multiple, options, size, instructions, metadata:

>>> field = Field('myfield')
>>> field.set(label='My field', renderer=SelectFieldRenderer,
...            options=[('Value', 1)])
AttributeField(myfield)
>>> field.label_text
'My field'
>>> field.renderer
<SelectFieldRenderer for AttributeField(myfield)>
textarea(size=None)
Render the field as a textarea. Size must be a string (“25x10”) or tuple (25, 10).
validate(validator)
Add the validator function to the list of validation routines to run when the FieldSet‘s validate method is run. Validator functions take one parameter: the value to validate. This value will have already been turned into the appropriate data type for the given Field (string, int, float, etc.). It should raise ValidationError if validation fails with a message explaining the cause of failure.
value

The value of this Field: use the corresponding value in the bound data, if any; otherwise, use the value in the bound model. For SQLAlchemy models, if there is still no value, use the default defined on the corresponding Column.

For SQLAlchemy collections, a list of the primary key values of the items in the collection is returned.

Invalid form data will cause an error to be raised. Controllers should thus validate first. Renderers should thus never access .value; use .model_value instead.

value_objects
This is the same as value, except that when used with ForeignKeys, instead of returning a list of primary keys, it will return a list of objects.
with_html(**html_options)

Give some HTML options to renderer.

Trailing underscore (_) characters will be stripped. For example, you might want to add a class attribute to your checkbox. You would need to specify .options(class_=’someclass’).

For WebHelpers-aware people: those parameters will be passed to the text_area(), password(), text(), etc.. webhelpers.

NOTE: Those options can override generated attributes and can mess
the sync calls, or label-tag associations (if you change name, or id for example). Use with caution.
with_metadata(**attrs)

Attach some metadata attributes to the Field, to be used by conditions in templates.

Example usage:

>>> test = Field('test')
>>> field = test.with_metadata(instructions='use this widget this way')
...

And further in your templates you can verify:

>>> 'instructions' in field.metadata
True

and display the content in a <span> or something.

with_null_as(option)
Render null as the given option tuple of text, value.
with_renderer(renderer)
Return a copy of this Field, with a different renderer. Used for one-off renderer changes; if you want to change the renderer for all instances of a Field type, modify FieldSet.default_renderers instead.
class formalchemy.fields.Field(name=None, type=<class 'sqlalchemy.types.String'>, value=None, **kwattrs)

A manually-added form field

Create a new Field object.

  • name:

    field name

  • type=types.String:

    data type, from formalchemy.types (Integer, Float, String, Binary, Boolean, Date, DateTime, Time) or a custom type

  • value=None:

    default value. If value is a callable, it will be passed the current bound model instance when the value is read. This allows creating a Field whose value depends on the model once, then binding different instances to it later.

    • name: field name
    • type: data type, from formalchemy.types (Boolean, Integer, String, etc.), or a custom type for which you have added a renderer.
    • value: default value. If value is a callable, it will be passed the current bound model instance when the value is read. This allows creating a Field whose value depends on the model once, then binding different instances to it later.
sync()
Set the attribute’s value in model to the value given in data
class formalchemy.fields.AttributeField(instrumented_attribute, parent)

Field corresponding to an SQLAlchemy attribute.

>>> from formalchemy.tests import FieldSet, Order
>>> fs = FieldSet(Order)
>>> print fs.user.key
user
>>> print fs.user.name
user_id
relation_type()
The type of object in the collection (e.g., User). Calling this is only valid when is_relation is True.
sync()
Set the attribute’s value in model to the value given in data

Renderers

FieldRenderer

class formalchemy.fields.FieldRenderer(field)

This should be the super class of all Renderer classes.

Renderers generate the html corresponding to a single Field, and are also responsible for deserializing form data into Python objects.

Subclasses should override render and deserialize. See their docstrings for details.

deserialize()

Turns the user-submitted data into a Python value. (The raw data will be available in self.field.parent.data, or you can use _serialized_value if it is convenient.) For SQLAlchemy collections, return a list of primary keys, and !FormAlchemy will take care of turning that into a list of objects. For manually added collections, return a list of values.

You should only have to override this if you are using custom (e.g., Composite) types.

get_translator(**kwargs)
return a GNUTranslations object in the most convenient way
name
Name of rendered input element
render(**kwargs)
Render the field. Use self.name to get a unique name for the input element and id. self._value may also be useful if you are not rendering multiple input elements.
render_readonly(**kwargs)
render a string representation of the field value
value_objects

Same as value, except returns a list of objects instead of primary keys, when working with ForeignKeys.

Use this when your deserialize or render functions manipulates ForeignKey objects; adding, removing or changing display according to their contents.

TextFieldRenderer

class formalchemy.fields.TextFieldRenderer(field)
render a field as a text field

Render a string field:

>>> fs = FieldSet(One)
>>> fs.append(Field(name='text', type=types.String, value='a value'))

Edit mode:

>>> print fs.text.render()
<input id="One--text" name="One--text" type="text" value="a value" />

Read only mode:

>>> print fs.text.render_readonly()
a value

IntegerFieldRenderer

class formalchemy.fields.IntegerFieldRenderer(field)
render an integer as a text field

PasswordFieldRenderer

class formalchemy.fields.PasswordFieldRenderer(field)
Render a password field

Render a string field:

>>> fs = FieldSet(One)
>>> fs.append(Field(name='passwd').with_renderer(PasswordFieldRenderer))

Edit mode:

>>> print fs.passwd.render()
<input id="One--passwd" name="One--passwd" type="password" />

Read only mode:

>>> print fs.passwd.render_readonly()
******

TextAreaFieldRenderer

class formalchemy.fields.TextAreaFieldRenderer(field)
render a field as a textarea

Render a string field:

>>> fs = FieldSet(One)
>>> fs.append(Field(name='text',value='a value').with_renderer(TextAreaFieldRenderer))

Edit mode:

>>> print fs.text.render()
<textarea id="One--text" name="One--text">a value</textarea>

Read only mode:

>>> print fs.text.render_readonly()
a value

HiddenFieldRenderer

class formalchemy.fields.HiddenFieldRenderer(field)
render a field as an hidden field

Render a string field:

>>> fs = FieldSet(One)
>>> fs.append(Field(name='text', value='h').with_renderer(HiddenFieldRenderer))

Edit mode:

>>> print fs.render()
<input id="One--text" name="One--text" type="hidden" value="h" />

Read only mode:

>>> print fs.text.render_readonly()
<BLANKLINE>

CheckBoxFieldRenderer

class formalchemy.fields.CheckBoxFieldRenderer(field)
render a boolean value as checkbox field

FileFieldRenderer

class formalchemy.fields.FileFieldRenderer(*args, **kwargs)

render a file input field

render_readonly(**kwargs)
render only the binary size in a human readable format but you can override it to whatever you want

DateFieldRenderer

class formalchemy.fields.DateFieldRenderer(field)
Render a date field

Render a date field:

>>> date = datetime(2000, 12, 31, 9, 00)
>>> fs = FieldSet(One)
>>> fs.append(Field(name='date', type=types.Date, value=date))

Edit mode:

>>> print pretty_html(fs.date.render())  #doctest: +ELLIPSIS
<span id="One--date">
 <select id="One--date__month" name="One--date__month">
  <option value="MM">
   Month
  </option>
  <option value="1">
   January
  </option>
...
  <option selected="selected" value="12">
   December
  </option>
 </select>
 <select id="One--date__day" name="One--date__day">
  <option value="DD">
   Day
  </option>
  <option value="1">
   1
  </option>
...
  <option selected="selected" value="31">
   31
  </option>
 </select>
 <input id="One--date__year" maxlength="4" name="One--date__year" size="4" type="text" value="2000" />
</span>

Read only mode:

>>> print fs.date.render_readonly()
2000-12-31
class formalchemy.fields.TimeFieldRenderer(field)
Render a time field

Render a time field:

>>> time = datetime(2000, 12, 31, 9, 03, 30).time()
>>> fs = FieldSet(One)
>>> fs.append(Field(name='time', type=types.Time, value=time))

Edit mode:

>>> print pretty_html(fs.time.render())  #doctest: +ELLIPSIS
<span id="One--time">
 <select id="One--time__hour" name="One--time__hour">
  <option value="HH">
   HH
  </option>
  <option value="0">
   0
  </option>
...
  <option selected="selected" value="9">
   9
  </option>
...
  <option value="23">
   23
  </option>
 </select>
 :
 <select id="One--time__minute" name="One--time__minute">
  <option value="MM">
   MM
  </option>
  <option value="0">
   0
  </option>
...
  <option selected="selected" value="3">
   3
  </option>
...
  <option value="59">
   59
  </option>
 </select>
 :
 <select id="One--time__second" name="One--time__second">
  <option value="SS">
   SS
  </option>
  <option value="0">
   0
  </option>
...
  <option selected="selected" value="30">
   30
  </option>
...
  <option value="59">
   59
  </option>
 </select>
</span>

Read only mode:

>>> print fs.time.render_readonly()
09:03:30

DateTimeFieldRenderer

class formalchemy.fields.DateTimeFieldRenderer(field)
Render a date time field

Render a datetime field:

>>> datetime = datetime(2000, 12, 31, 9, 03, 30)
>>> fs = FieldSet(One)
>>> fs.append(Field(name='datetime', type=types.DateTime, value=datetime))

Edit mode:

>>> print pretty_html(fs.datetime.render())  #doctest: +ELLIPSIS
<span id="One--datetime">
 <select id="One--datetime__month" name="One--datetime__month">
  <option value="MM">
   Month
  </option>
...
  <option selected="selected" value="12">
   December
  </option>
 </select>
 <select id="One--datetime__day" name="One--datetime__day">
  <option value="DD">
   Day
  </option>
...
  <option selected="selected" value="31">
   31
  </option>
 </select>
 <input id="One--datetime__year" maxlength="4" name="One--datetime__year" size="4" type="text" value="2000" />
 <select id="One--datetime__hour" name="One--datetime__hour">
  <option value="HH">
   HH
  </option>
...
  <option selected="selected" value="9">
   9
  </option>
...
 </select>
 :
 <select id="One--datetime__minute" name="One--datetime__minute">
  <option value="MM">
   MM
  </option>
...
  <option selected="selected" value="3">
   3
  </option>
...
 </select>
 :
 <select id="One--datetime__second" name="One--datetime__second">
  <option value="SS">
   SS
  </option>
...
  <option selected="selected" value="30">
   30
  </option>
...
 </select>
</span>

Read only mode:

>>> print fs.datetime.render_readonly()
2000-12-31 09:03:30

RadioSet

class formalchemy.fields.RadioSet(field)
render a field as radio

CheckBoxSet

class formalchemy.fields.CheckBoxSet(field)
static widget(name, value='1', checked=False, **options)
Creates a check box.

SelectFieldRenderer

class formalchemy.fields.SelectFieldRenderer(field)

render a field as select

render_readonly(options=None, **kwargs)
render a string representation of the field value. Try to retrieve a value from options

EscapingReadonlyRenderer

class formalchemy.fields.EscapingReadonlyRenderer(field)
In readonly mode, html-escapes the output of the default renderer for this field type. (Escaping is not performed by default because it is sometimes useful to have the renderer include raw html in its output. The FormAlchemy admin app extension for Pylons uses this, for instance.)

Custom renderer

You can write your own FieldRenderer s to customize the widget (input element[s]) used to edit different types of fields...

  1. Subclass FieldRenderer.

    1. Override render to return a string containing the HTML input elements desired. Use self.name to get a unique name and id for the input element. self._value may also be useful if you are not rendering multiple input elements.
    2. If you are rendering a custom type (any class you defined yourself), you will need to override deserialize as well. render turns the user-submitted data into a Python value. (The raw data will be available in self.field.parent.data, or you can use _serialized_value if it is convenient.) For SQLAlchemy collections, return a list of primary keys, and FormAlchemy will take care of turning that into a list of objects. For manually added collections, return a list of values.
    3. If you are rendering a builtin type with multiple input elements, override _serialized_value to return a single string combining the multiple input pieces. See the source for DateFieldRenderer for an example.
  2. Update FieldSet.default_renderers. default_renderers is a dict of FieldRenderer subclasses. The default contents of default_renderers is:

    default_renderers = {
        types.String: fields.TextFieldRenderer,
        types.Integer: fields.IntegerFieldRenderer,
        types.Boolean: fields.BooleanFieldRenderer,
        types.DateTime: fields.DateTimeFieldRendererRenderer,
        types.Date: fields.DateFieldRenderer,
        types.Time: fields.TimeFieldRenderer,
        types.Binary: fields.FileFieldRenderer,
        'dropdown': fields.SelectFieldRenderer,
        'checkbox': fields.CheckBoxSet,
        'radio': fields.RadioSet,
        'password': fields.PasswordFieldRenderer,
        'textarea': fields.TextAreaFieldRenderer,
    }
    

For instance, to make Boolean s render as select fields with Yes/No options by default, you could write:

>>> from formalchemy.fields import SelectFieldRenderer
>>> class BooleanSelectRenderer(SelectFieldRenderer):
...     def render(self, **kwargs):
...         kwargs['options'] = [('Yes', True), ('No', False)]
...         return SelectFieldRenderer.render(self, **kwargs)

>>> FieldSet.default_renderers[types.Boolean] = BooleanSelectRenderer

Of course, you can subclass FieldSet if you don’t want to change the defaults globally.

One more example, this one to use the JQuery UI DatePicker to render Date objects:

>>> from formalchemy.fields import FieldRenderer
>>> class DatePickerFieldRenderer(FieldRenderer):
...     def render(self):
...         value= self.value and self.value or ''
...         vars = dict(name=self.name, value=value)
...         return """
...            <input id="%(name)s" name="%(name)s"
...                   type="text" value="%(value)s">
...            <script type="text/javascript">
...              $('#%(name)s').datepicker({dateFormat: 'yy-mm-dd'})
...            </script>
...         """ % vars

(Obviously the page template will need to add references to the jquery library and css.)

Another example to render a link field:

>>> class LinkFieldRenderer(FieldRenderer):
...     def render(self, **kwargs):
...         """render html for edit mode"""
...         from formalchemy import helpers as h
...         return h.text_field(self.name, value=self._value, **kwargs)
...     def render_readonly(self, **kwargs):
...         """render html for read only mode"""
...         kwargs = {'value':self.field.raw_value}
...         return '<a href="%(value)s">%(value)s</a>' % kwargs

Then bind it to a specific field:

>>> from formalchemy.tests import *
>>> fs = FieldSet(One)
>>> fs.append(Field('link', value='http://www.formalchemy.org'))
>>> fs.configure(include=[fs.link.with_renderer(LinkFieldRenderer)])

Here is the result for edit mode:

>>> print fs.render()
<div>
 <label class="field_opt" for="One--link">
  Link
 </label>
 <input id="One--link" name="One--link" type="text" value="http://www.formalchemy.org" />
</div>
<script type="text/javascript">
 //<![CDATA[
document.getElementById("One--link").focus();
//]]>
</script>

And for read only mode:

>>> fs.readonly = True
>>> print fs.render()
<tbody>
 <tr>
  <td class="field_readonly">
   Link:
  </td>
  <td>
   <a href="http://www.formalchemy.org">
    http://www.formalchemy.org
   </a>
  </td>
 </tr>
</tbody>