Field can be defined with validation chain, and will be validated when value is assigned. For example:
from dictify import Field
username = Field(required=True).instance(str).match('[a-zA-Z0-9 ._-]+$')
email = Field(required=True).instance(str).match('.+@.+')
username.value = 'user'
email.value = 'user@example.com'
username.value = 0 # Invalid, value is not assigned.
email.value = 'user' # Invalid, value is not assigned.
For complex or nested data structure, Feild can be defined and managed by Model which map and validate Field to python native dict instance. For example:
from dictify import Field, Model
class Contact(Model):
type = Field(require=True).instance(str)\
.verify(lambda value: value in ['phone', 'email', 'address'])
note = Field().instance(str)\
.verify(lambda value: len(value) <= 250)
value = Field(require=True).instance(str)\
.verify(lambda value: len(value) <= 1000)
class User(Model):
username = Field(required=True).instance(str).match('[a-zA-Z0-9 ._-]+$')
email = Field(required=True).instance(str).match('.+@.+')
contacts = Field().listof(Contact)
user = User({'username': 'user', 'email': 'user@example.com'})
user['username'] = 0 # Invalid, value won't be assigned.
user['email'] = 'user' # Invalid, won't be assigned.
user['age'] = 30 # Error, undefined field.
By default, Model object will be created in strict mode which won't allow value assignment on undefined field. Set strict=False
at Model creation to change this behavior.
user = User({'username': 'user', 'email': 'user@example.com'}, strict=False)
# Value assignment on undefined field is allowed.
user['age'] = 30
Model.dict()
returns native data as dict
and list
. This could be useful
to send data though network or use with pickle()
when your model has Model
or
List
in subtree.
user = User({
'username': 'user',
'email': 'user@example.com',
'contacts': [Contact({type: 'phone', value: '111-800-0000'})]
})
pickle(user) # Error
pickle(user.dict()) # Ok
Defined Field
can be reused for partial data validation. For example, when user want to update user’s email later, User.email
can be used as class attributes to validate email without create the whole User object.
email = request.args.get('email') # pseudo code to get email sent from user.
try:
User.email.value = email
# To do : Update user's email to database.
except dictify.FieldError:
# To do : Report error.
Define post_validation()
method and it will be applied everytime data is set.
class User(Model):
username = Field(required=True).instance(str).match('[a-zA-Z0-9 ._-]+$')
email = Field(required=True).instance(str).match('.+@.+')
email_backup = Field(require=True).instance(str).match('.+@.+')
def post_validation(self):
# Email duplication check, all built-in dictionary methods can be used.
assert self.get('email') != self.get('email_backup')