Either set <min_length>1</min_length>, or set missing_value= so that an empty list is counted as a missing value. I'm not sure there's a way to do the latter in supermodel XML -- <missing_value></missing_value> may be interpreted as None -- so try the former.
You can write a custom field validator like this:
from z3c.form import validator
from zope.interface import Invalid
class CustomValidator(validator.SimpleFieldValidator):
def validate(self, value):
super(CustomValidator, self).validate(value)
if value:
if [value is not valid]:
raise Invalid(u'Value is not valid')
And use it from supermodel XML like this:
form:validator="dotted.path.to.CustomValidator"
Note that a validator specified in this way overrides the default z3c.form field validator, so it's important to remember to call super().validate.
Unless I am understanding incorrectly, setting missing_value to a mutable collection type might have some shared-state side-effects, if you are not careful?
For forms, likely not a big deal because a round-trip through data converters cleans this up, but if you construct an item programmatically, I suppose there is a possibility of having multiple instances of content reference the same list.
Since this is a list, not a PersistentList, Persistence round-trip can also incidentally reduce likelihood of accidentally sharing state (post-commit, across threads), but I have been bit more than once by using a mutable collection as a default for a schema field (defaultFactory=list might work better?).
Good point, Sean. I was thinking narrowly about how zope.schema compares the value to the field's missing_value during "required" validation, but not about the other implications of specifying a list here.