formalchemy.ext.zope – zope.schema support

This module provides an experimental subclass of FieldSet to support zope.schema‘s schema. Simple validation is supported. Invariant is not supported.

Available fields

Not all fields are supported. You can use TextLine, Text, Int, Bool, Float, Date, Datetime, Time, and Choice.

Usage

Here is a simple example. First we need a schema:

>>> class IPet(interface.Interface):
...     name = schema.Text(title=u'Name', required=True)
...     type = schema.TextLine(title=u'Type', required=True)
...     age = schema.Int(min=1)
...     owner = schema.TextLine(title=u'Owner')
...     birthdate = schema.Date(title=u'Birth date')
...     colour = schema.Choice(title=u'Colour',
...                            values=['Brown', 'Black'])
...     friends = schema.List(title=u'Friends', value_type=schema.Choice(['cat', 'dog', 'bulldog']))

Initialize FieldSet with schema:

>>> fs = FieldSet(IPet)

Create a class to store values. If your class does not implement the form interface the FieldSet will generate an adapter for you:

>>> class Pet(FlexibleDict):pass
>>> p = Pet(name='dewey', type='cat', owner='gawel', friends=['cat', 'dog'])
>>> fs = fs.bind(p)

Fields are aware of schema attributes:

>>> fs.name.is_required()
True

We can use the form:

>>> print fs.render().strip() 
<div>
  <label class="field_req" for="Pet--name">Name</label>
  <textarea id="Pet--name" name="Pet--name">dewey</textarea>
</div>
<script type="text/javascript">
//<![CDATA[
document.getElementById("Pet--name").focus();
//]]>
</script>
<div>
  <label class="field_req" for="Pet--type">Type</label>
  <input id="Pet--type" name="Pet--type" type="text" value="cat" />
</div>
<div>
  <label class="field_req" for="Pet--age">age</label>
  <input id="Pet--age" name="Pet--age" type="text" />
</div>
<div>
  <label class="field_req" for="Pet--owner">Owner</label>
  <input id="Pet--owner" name="Pet--owner" type="text" value="gawel" />
</div>
<div>
  <label class="field_req" for="Pet--birthdate">Birth date</label>
  <span id="Pet--birthdate"><select id="Pet--birthdate__month" name="Pet--birthdate__month">
<option selected="selected" value="MM">Month</option>
<option value="1">January</option>
<option value="2">February</option>
...
<option value="31">31</option>
</select>
<input id="Pet--birthdate__year" maxlength="4" name="Pet--birthdate__year" size="4" type="text" value="YYYY" /></span>
</div>
<div>
  <label class="field_req" for="Pet--colour">Colour</label>
  <select id="Pet--colour" name="Pet--colour">
<option value="Brown">Brown</option>
<option value="Black">Black</option>
</select>
</div>
<div>
  <label class="field_req" for="Pet--friends">Friends</label>
  <select id="Pet--friends" multiple="multiple" name="Pet--friends">
<option value="bulldog">bulldog</option>
<option selected="selected" value="dog">dog</option>
<option selected="selected" value="cat">cat</option>
</select>
</div>

Ok, let’s assume that validation and syncing works:

>>> fs.configure(include=[fs.name])
>>> fs.rebind(p, data={'Pet--name':'minou'})
>>> fs.validate()
True
>>> fs.sync()
>>> fs.name.value
u'minou'
>>> p.name
u'minou'
>>> fs.configure(include=[fs.age])
>>> fs.rebind(p, data={'Pet--age':'-1'})
>>> fs.validate()
False
>>> fs.age.errors
[u'Value is too small']
>>> fs.configure(include=[fs.colour])
>>> fs.rebind(p, data={'Pet--colour':'Yellow'})
>>> fs.validate()
False
>>> fs.colour.errors
[u'Constraint not satisfied']
>>> fs.rebind(p, data={'Pet--colour':'Brown'})
>>> fs.validate()
True
>>> fs.sync()
>>> fs.colour.value
u'Brown'
>>> p.colour
u'Brown'

Looks nice ! Let’s use the grid:

>>> grid = Grid(IPet)
>>> grid = grid.bind([p])
>>> print grid.render().strip() 
<thead>
  <tr>
      <th>Name</th>
      <th>Type</th>
      <th>age</th>
      <th>Owner</th>
      <th>Birth date</th>
      <th>Colour</th>
      <th>Friends</th>
  </tr>
...
  <tr class="even">
    <td>
      <textarea id="Pet--name" name="Pet--name">minou</textarea>
    </td>
    <td>
      <input id="Pet--type" name="Pet--type" type="text" value="cat" />
    </td>
    <td>
      <input id="Pet--age" name="Pet--age" type="text" />
    </td>
    <td>
      <input id="Pet--owner" name="Pet--owner" type="text" value="gawel" />
    </td>
    <td>
      <span id="Pet--birthdate"><select id="Pet--birthdate__month" name="Pet--birthdate__month">
<option selected="selected" value="MM">Month</option>
<option value="1">January</option>
<option value="2">February</option>
<option value="3">March</option>
<option value="4">April</option>
<option value="5">May</option>
<option value="6">June</option>
<option value="7">July</option>
<option value="8">August</option>
<option value="9">September</option>
<option value="10">October</option>
<option value="11">November</option>
<option value="12">December</option>
</select>
<select id="Pet--birthdate__day" name="Pet--birthdate__day">
<option selected="selected" value="DD">Day</option>
<option value="1">1</option>
...
<option value="31">31</option>
</select>
<input id="Pet--birthdate__year" maxlength="4" name="Pet--birthdate__year" size="4" type="text" value="YYYY" /></span>
    </td>
    <td>
      <select id="Pet--colour" name="Pet--colour">
<option selected="selected" value="Brown">Brown</option>
<option value="Black">Black</option>
</select>
    </td>
    <td>
      <select id="Pet--friends" multiple="multiple" name="Pet--friends">
<option value="bulldog">bulldog</option>
<option selected="selected" value="dog">dog</option>
<option selected="selected" value="cat">cat</option>
</select>
    </td>
  </tr>
</tbody>

Classes definitions

Field

class formalchemy.ext.zope.Field(name=None, type=<class 'sqlalchemy.types.String'>, value=None, **kwattrs)

Field aware of zope schema. See formalchemy.fields.AbstractField for full api.

Create a new Field object.

  • name:

    field name

  • type=types.String:

    data type, from formalchemy.types (Integer, Float, String, LargeBinary, 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.

FieldSet

class formalchemy.ext.zope.FieldSet(model, **kwargs)

FieldSet aware of zope schema. See formalchemy.forms.FieldSet for full api.

Grid

class formalchemy.ext.zope.Grid(cls, instances=[], **kwargs)

Grid aware of zope schema. See formalchemy.tables.Grid for full api.

Utilities

class formalchemy.ext.zope.Pk(attr='__name__')

FormAlchemy use a _pk attribute to identify objects. You can use this property to bind another attribute as a primary key:

>>> class Content(object):
...     _pk = Pk()
...     __name__ = 'primary_key'

>>> content = Content()
>>> content._pk
'primary_key'

>>> content._pk = 'another_key'
>>> content.__name__
'another_key'

>>> class Content(object):
...     _pk = Pk('uid')
...     uid = 'primary_key'

>>> content = Content()
>>> content._pk
'primary_key'

>>> fields._pk(content)
'primary_key'
class formalchemy.ext.zope.FlexibleModel(context=None, **kwargs)

A flexible object to easy adapt most python classes:

>>> obj = FlexibleModel(owner='gawel')
>>> obj.owner == obj.get('owner') == obj['owner'] == 'gawel'
True
>>> obj._pk is None
True

If your object provide an uuid attribute then FormAlchemy will use it has primary key:

>>> import uuid
>>> obj = FlexibleModel(uuid=uuid.uuid4())
>>> obj._pk is None
False
class formalchemy.ext.zope.FlexibleDict(context=None, **kwargs)

like FlexibleModel but inherit from dict:

>>> obj = FlexibleDict(owner='gawel')
>>> obj.owner == obj.get('owner') == obj['owner'] == 'gawel'
True
>>> isinstance(obj, dict)
True
>>> 'owner' in obj
True
formalchemy.ext.zope.gen_model(iface, klass=None, dict_like=False)

return a new FlexibleModel or FlexibleDict factory who provide iface:

>>> class ITitle(interfaces.Interface):
...     title = schema.TextLine(title=u'title')

>>> factory = gen_model(ITitle)
>>> adapted = factory()
>>> ITitle.providedBy(adapted)
True

>>> class Title(object):
...     title = None
>>> obj = Title()
>>> adapted = factory(obj)
>>> adapted.context is obj
True
>>> adapted.title = 'my title'
>>> obj.title
'my title'

>>> obj = dict()
>>> adapted = factory(obj)
>>> adapted.context is obj
True
>>> adapted.title = 'my title'
>>> obj['title']
'my title'

Table Of Contents

Previous topic

formalchemy.ext.rdf – rdfalchemy support

This Page