I'd like to create a content type that uses collective.z3cform.datagridfield. I have been trying to follow the example mentioned in this presentation: http://glicksoftware.com/presentations/dexterity-in-the-wild
The example demonstrates referencing a second schema from the main schema. This is my attempt.
<?xml version="1.0" ?>
<model xmlns="http://namespaces.plone.org/supermodel/schema"
xmlns:form="http://namespaces.plone.org/supermodel/form">
<field name="telephone" type="zope.schema.List"
form:widget="collective.z3cform.datagridfield.DataGridFieldFactory">
<title>Telephone</title>
<description>Enter telephone numbers here</description>
<max_length>10</max_length>
<min_length>2</min_length>
<missing_value/>
<readonly>False</readonly>
<required>False</required>
<value_type type="collective.z3cform.datagridfield.DictRow">
<title>Number</title>
<schema>mypackage.mytype.IPhoneSchema</schema>
</value_type>
</field>
</schema>
</model>
I define my second schema in mypackage/mytype.py to look like this:
from plone.supermodel import model
class IPhoneSchema(model.Schema):
"""Schema for dict rows used in DataGridFields
name is the 'real' name
token is the token used in the vocabularies
"""
#
model.load("models/phone.xml")
And then in models/phone.xml I have the following:
<?xml version="1.0" ?>
<model xmlns="http://namespaces.plone.org/supermodel/schema"
xmlns:form="http://namespaces.plone.org/supermodel/form">
<schema>
<field name="number" type="zope.schema.TextLine">
<description/>
<required>False</required>
<title>Number</title>
</field>
</schema>
</model>
When I start Plone I get the following error:
SupermodelParseError: 'module' object has no attribute 'mytype'
<schema>mypackage.mytype.IPhoneSchema</schema>
Effectively, both model xml files were defined in the mytype.py file. This caused an issue at runtime where mytype.py cannot call ... mytype.IPhoneSchema.
The solution was to create a phoneschema.py file independent of mytype.py with the following content:
from plone.supermodel import model
class IPhoneSchema(model.Schema):
"""Schema for dict rows used in DataGridFields they are used for individual phone numbers """ model.load("models/phone.xml")
Instead of calling mytype.IPhoneSchema, we can now call phoneschema.IPhoneSchema. I can include the phone schema in models/mytype.xml (see the example below).
...
<title>Telephone</title> <description>Enter telephone numbers here</description> <max_length>10</max_length> <min_length>2</min_length> <missing_value/> <readonly>False</readonly> <required>False</required> <value_type type="collective.z3cform.datagridfield.DictRow"> <title>Number</title> <schema>mypackage.mytype.IPhoneSchema</schema> </value_type> </field>
...
Here's a diagram of the relationship, phoneschema.py 'loads' phone.xml:
For the sake of reference, the file tree of my product now would look something like this (I've put a star next to the key file in this scenario phoneschema.py which references the second model file):
...
├── __init__.py
├── configure.zcml
├── mytype.py
├── mytype_templates
│ └── view.pt
├── models
│ ├── mytype.xml
│ └── phone.xml
├── *phoneschema.py
...