Reputation: 14961
When creating Dexterity types programmatically, is it possible to validate the data being passed to the factory as if it was coming from a form?
I have a Dexterity content type with a number of constraints, invariants & validators:
from zope import schema
from zope import interface
from z3c.form import validator
from plone import dexterity
from plone.directives import form
from five import grok
def is_not_foo(value):
return value is not 'foo'
class IMyType(form.Schema):
my_value = schema.TextLine(
constraint = is_not_foo
)
min = schema.Int(default=0)
max = schema.Int(default=99)
@interface.invariant
def max_more_than_min(data):
if data.min is not None and data.max is not None:
if data.min >= data.max:
raise interface.Invalid( u'Min is more than Max' )
@form.error_message(form=IMyType['my_value'], error=schema.interfaces.ConstraintNotSatisfied)
def error_my_value_is_foo(value):
return u'my_value must not be "foo"'
class ValidateMyValue(validator.SimpleFieldValidator):
def validate(self, value):
if value is not None:
# value passes some test
validator.WidgetValidatorDiscriminators(
ValidateMyValue,
form = IMyType['my_value'],
)
grok.global_adapter(ValidateMyValue)
To ensure that all instances of MyType have the right defaults, I've made a custom class for it with attributes mapped using FieldProperty, and assigned it in the type's FTI declaration:
class MyType(dexterity.content.Item):
interface.implements(IMyType)
my_value = schema.fieldproperty.FieldProperty(IMyType['my_value'])
min = schema.fieldproperty.FieldProperty(IMyType['min'])
max = schema.fieldproperty.FieldProperty(IMyType['max'])
However, when using plone.dexterity.utils.createContentInContainer
, it is possible to instantiate an object that doesn't comply with the constraints etc imposed. Ideally, I'd like to be able to perform this validation myself before doing the creation.
Is there a simple approach here I'm missing? I've taken a brief look at collective.transmogrifier but I see no mention of input validation.
Thanks.
Upvotes: 0
Views: 446
Reputation: 1124718
You can use the zope.schema.getValidationErrors()
function:
newInstance = createContentInContainer(folder, id, **schemavalues)
errors = getValidationErrors(IMyType, newInstance)
if errors:
# Schema not validated; errors is a sequence of (field, exception) tuples
# field is None if the error is for an invariant.
Upvotes: 1