FlyForms reference¶
Forms¶
Class Form
is the root class of FlyForms that provide the highest level API for data structures
validation and mapping. All user-defined forms must inherit this class.
Form class¶
-
class
flyforms.core.
Form
(**data)[source]¶ The root class for all Forms
Parameters: data (dict) – additional data to form When a Form is instantiated you can access given data via instance attributes or get everything at once using
to_python()
methodProperties
-
is_bound
¶ Checks is Form instance bound. Returns True if there are no
UnboundField
instances in_raw_data
. Otherwise, False.
-
is_valid
¶ Checks is Form instance valid. Returns True if there are no errors. Otherwise, False.
Attributes
-
_raw_data
¶ Normal Python
dict
contains all Form data (even unbind fields)
-
_fields
¶ Python
set
contains all defined fields names
-
_meta
¶ Instance of
FormMetaOptions
contains Form meta information
Methods
-
to_python
()[source]¶ Changed in version 1.0.0.
New in version 0.3.0.
Get form data as a
dict
Returns: dictionary that contains bound data of valid form Raises UnboundForm: if is_valid
returns False
-
classmethod
validate
(**schema)[source]¶ Class method provides data validation without
Form
instantiation by callingField.validate()
method of all declared fieldsParameters: schema – data to validate Returns: boolean flag is data valid for this Form
For more information about
validate()
method see In flight data validation.-
Defining Forms¶
Forms defining is quite simply process. All you need is to make a subclass of Form
and define fields as class attributes.
If you need to extend Forms, inheritance is available.
New Form will contain all fields of the parent form as well as it’s own.
from flyforms import Form, IntField
class GrandParent(Form):
grandparent_field = IntField()
class Parent(GrandParent):
parent_field = IntField()
class Child(Parent):
child_field = IntField()
if __name__ == '__main__':
print(Child._fields) # >> set(['parent_field', 'child_field', 'grandparent_field'])
By the way, multiple Forms inheritance is also possible. It will be done in full compliance with the Python MRO:
from flyforms import Form, IntField, EmailField
class GrandParent(Form):
grandparent = IntField()
class Mother(GrandParent):
mother = IntField()
parent = EmailField()
class Father(GrandParent):
father = IntField()
parent = IntField()
class Child(Mother, Father):
child = IntField()
if __name__ == '__main__':
print(Child._fields) # >> set(['parent', 'mother', 'grandparent', 'child', 'father'])
print(Child.parent) # >> <flyforms.fields.EmailField object at ...>
Using Forms¶
Typical Forms usage schema looks like:
class MyForm(Form):
# Your form definition
if __name__ == '__main__':
f = MyForm(**data) # form instantiation
if f.is_valid:
# do something with form
else:
# handle form errors
Note
Verification form by is_valid
is a more generalized than is_bound
.
In general, Form may be bound but not valid.
Therefore, we recommend you to use is_valid
property for Form bound verification.
For a better understanding of the internal structure of the Form
class see Low-level API section.
When Form instantiated, you can access bind data within form instance attributes:
class MyForm(Form):
field = StringField()
if __name__ == '__main__':
f = MyForm(**data) # form instantiation
print(f.field) # >> bound value will be printed
FlyForms Field
API allow you to set default values for form fields. You can use it together with passing
required=False
to field constructor (for more information about Field
API see Fields).
If you do not pass the value of not required field during form instantiation, you`ll got the default value:
class MyForm(Form):
field = StringField(required=False, default="Hello!")
if __name__ == '__main__':
f = MyForm() # form instantiation
print(f.field) # >> Hello!
But if you’ll pass required=False
to field constructor without passing a default value,
you`ll got an unbound field:
class MyForm(Form):
field = StringField(required=False)
if __name__ == '__main__':
f = MyForm() # form instantiation
print(f.field) # >> <UnboundStringField(field, errors: {})>
By default, representation of unbound fields provided by UnboundField
.
If you want to access all bound data, use to_python()
method that returns dict
which contains all bound data.
But if there are any errors, UnboundForm
exception will be raised.
-
class
flyforms.core.
UnboundForm
[source]¶ Raises when you try to serialize an
Form
bound with invalid data
FlyForms also provides you to dump Form data into json string within the to_json()
method.
In flight data validation¶
If you already have defined Form and you want to just validate a data structure within that, you can use
Form.validate()
class method.
Goal
The main goal is that no new objects will be created when you call Form.validate()
.
Usage
# coding=utf-8
from flyforms.form import Form
from flyforms.fields import EmailField, StringField
class LoginForm(Form):
email = EmailField()
password = StringField(
min_length=8,
regex=r"^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#\$%\^&\*])",
max_length=64
)
if __name__ == '__main__':
# Valid data
r1 = LoginForm.validate(email="smith@gmail.com", password="Qw3rT!y_")
print(r1) # >>> True
# Bad data
r2 = LoginForm.validate(email="smith@gmail.com", password="Qwerty")
print(r2) # >>> False
Unbound fields rendering¶
By default, all unbound fields are replaced with UnboundField
instances.
You can customize it using FormMetaOptions.unbound_field_render
in FormMetaOptions
definition for your Form.
Forms customization¶
You can define an Meta
class in your Form definition to customize it`s behaviour.
API
-
class
flyforms.core.
FormMetaOptions
(**kwargs)[source]¶ Provides customization of
Form
instances behaviour.-
skip_extra
¶ (default:
False
) if not defined, all extra field will be interpreted as errors during Form instantiation
-
unbound_field_render
¶ (default:
UnboundField
) all unbound Form fields will be replaced with instances of this class
-
Usage
# coding=utf-8
from flyforms import Form, IntField
class MyUnboundField(object):
def __init__(self, *args, **kwargs):
pass
class MyForm(Form):
class Meta:
skip_extra = True
unbound_field_render = MyUnboundField
field = IntField()
not_required = IntField(required=False)
if __name__ == '__main__':
f = MyForm(**{
"field": 1,
"extra_field1": None,
"extra_field2": object()
})
print(f.is_valid) # >> True
print(f.to_python()) # >> {'field': 1}
print(f.not_required) # >> <__main__.MyUnboundField object at ...>
Note
There is no inheritance of Meta
class.
It`ll have an effect only in a form where it has been defined.
But if you use EmbeddedFormField
with form in which the Meta
class defined, it
FormMetaOptions.skip_extra
attribute will be used to customize it binding process.
Low-level API¶
Warning
This section provides information about core classes API of FlyForms. You should not use it, but understanding. It is necessary to extending and form behavior customization in some specific cases.
-
class
flyforms.core.
FormMeta
[source]¶ The metaclass for Form and it’s subclasses. It`s main responsibility - find all declared fields in the form and it`s bases. It also replaces the declared fields with
FormField
descriptor.
-
class
flyforms.core.
FormField
(name, field_obj)[source]¶ The descriptor for fields in
Form
. It`s behavior depends on whether the form is instantiated or not.Parameters: - name – declared field class attribute name
- field_obj – instance of declared field
-
__get__
(instance, owner)[source]¶ If form is instantiated returns bound data, otherwise - instance of declared field
-
__set__
(instance, value)[source]¶ Calls
Field.bind()
method and puts the result toForm._raw_data
.If
Field.bind()
returnsUNSET
value or there are errors (second return value is notNone
) an instance ofUnboundField
will be put intoForm._raw_data
.If form is instantiated
AttributeError
will be raised.
Form data manipulations¶
Since version 1.0.0 FlyForms provides you to load and dump your Form data to JSON format.
We decided to bring this functionality into separate functions, collected in module flyforms.form
.
For JSON encoding and decoding we use json
module.
Eventually, the data cached in Form constitute an ordinary Python dict
, so we decided to avoid complicating.
-
flyforms.form.
to_json
(form, **kwargs)[source]¶ New in version 1.0.0.
Dump Form data to json string
Parameters: - form – instance of
Form
subclass - kwargs – additional arguments passed to json.dumps
Returns: encoded json-string
- form – instance of
-
flyforms.form.
from_json
(form_cls, json_str, **kwargs)[source]¶ Creates and returns new Form instance bound with data from passed json string
Parameters: - form_cls –
Form
subclass - json_str – json string
- kwargs – additional arguments for
json.loads
Returns: bound Form instantiated from
form_cls
- form_cls –
-
flyforms.form.
validate_json
(form_cls, json_str, **kwargs)[source]¶ Validates given json string data within passed
Form
subclass by calling it`sForm.validate()
classmethod.It is useful when you don`t need to load data from json to your Form.
Parameters: - form_cls –
Form
subclass - json_str – json string
- kwargs – additional arguments for
json.loads
Returns: bound Form instantiated from
form_cls
- form_cls –
Fields¶
Fields represent a set of rules for data validation within set of Validator
instances.
When you define your custom Form
subclass you define Fields as its class attributes.
This is the most common usage of Fields, but nothing prevents you to use them standalone.
Field class¶
-
class
flyforms.fields.
Field
(required=True, null=False, validators=(), default=UNSET)[source]¶ This is the base class for all builtin and user defined Fields.
Parameters: Raises TypeError: if passed arguments invalid
Class attributes
-
value_types
¶ valid types of field value
Attributes
-
required
¶ Boolean flag passed to constructor
-
default
¶ The default value for Field, which will be used when no data available to bind
-
base_validators
¶ List of attached by processing construction arguments
Validators
-
custom_validators
¶ Iterable object contains
custom_validators
passed to constructor
Property
-
validators
¶ Changed in version 1.0.0.
Generator that returns
base_validators
andcustom_validators
items successively
Methods
-
bind
(value)[source]¶ New in version 0.2.0.
Changed in version 1.0.0.
Validates given value via defined set of
Validators
, wraps it intowrapper
and returns wrapped value andNone
in second position. If some errors occurred returns anUNSET
and this errorsIf value is mutable obj (for example
list
) it’ll be converted to immutable (for exampletuple
)Parameters: value – the value to bind Returns: bound value and occurred errors (if there were no errors - None
will be returned in second position)
Hooks
-
static
field_binding_hook
(method)[source]¶ Hook to avoid code duplicating in
Field.bind()
method realizations that provides checking the value toNone
andUNSET
You may use it as decorator for
Field.bind()
method in your custom fields
-
static
field_validation_hook
(method)[source]¶ Hook to avoid code duplicating in
Field.validate()
method realizations that provides checking the value toNone
andUNSET
You may use it as decorator for
Field.validate()
method in your custom fields
-
Builtin fields summary¶
This section provides summary for all builtin Fields and API for its base classes. For more information about each Field, see it`s API reference.
Note
Since version 1.0.0 inheritance model for builtin Fields has been changed.
Field | Base class | Reflected type | Bound value type |
---|---|---|---|
StringField |
SelectField |
Python 2.x: Python 3.x: |
Python 2.x Python 3.x: |
IntField |
int |
||
BooleanField |
bool |
||
FloatField |
IntField |
float |
float |
EmailField |
StringField |
same with StringField |
|
Ip4Field |
StringField |
same with StringField |
|
ListField |
SequenceField |
Iterable |
tuple |
ArrayField |
|||
DatetimeField |
Field |
same with StringField |
|
DictField |
dict |
FrozenDict |
|
EmbeddedFormField |
For more information see Embedded Forms |
-
class
flyforms.fields.
SelectField
(choices=(), **kwargs)[source]¶ New in version 1.0.0.
This is the base class for all Fields that reflect single values such as
int
,float
,bool
and etc. It provides to specify list of valid values (choices). Any passed values which are not in the defined choices will cause validation fails.Parameters: - required (bool) – boolean flag is this field required or may be
UNSET
- null (bool) – boolean flag is field value may be
None
- validators (list of callable) – the additional validators for field
- default (instance of value_types) – the default value of the field
- choices (Iterable) – iterable object contains possible values of this field
- required (bool) – boolean flag is this field required or may be
-
class
flyforms.fields.
SequenceField
(min_length=None, max_length=None, item_validators=(), **kwargs)[source]¶ New in version 1.0.0.
This is the base class for all Fields that reflect iterable values such as list, tuple and etc. It provides to specify such as minimum and maximum possible iterable length and validators for each item.
Parameters: - required (bool) – boolean flag is this field required or may be
UNSET
- null (bool) – boolean flag is field value may be
None
- validators (list of callable) – the additional validators for field
- default (instance of value_types) – the default value of the field
- min_length (int) – minimum iterable length
- max_length (int) – maximum iterable length
- item_validators (list of Callable) – the additional validators for every item
- required (bool) – boolean flag is this field required or may be
Builtin fields API¶
-
class
flyforms.fields.
StringField
(min_length=None, max_length=None, regex='', **kwargs)[source]¶ Reflects Python strings
Parameters: - required (bool) – boolean flag is this field required
- null (bool) – boolean flag is field value may be
None
- min_length (int or None) – the minimum length of the string
- max_length (int or None) – the maximum length of the string
- regex (str or regexp) – the regular expression to validate
- choices (iterable) – iterable object contains possible values of this field
- validators (list of callable) – the additional validators for field
- default (instance of value_types) – the default value of the field
-
class
flyforms.fields.
EmailField
(**kwargs)[source]¶ Reflects Python string corresponding to an email
Parameters: - required (bool) – boolean flag is this field required
- null (bool) – boolean flag is field value may be
None
- choices (iterable) – iterable object contains possible values of this field
- validators (list of callable) – the additional validators for field
- default (instance of value_types) – the default value of the field
-
class
flyforms.fields.
Ip4Field
(**kwargs)[source]¶ Reflects Python string corresponding to an IPv4 address
Parameters: - required (bool) – boolean flag is this field required
- null (bool) – boolean flag is field value may be
None
- choices (iterable) – iterable object contains possible values of this field
- validators (list of callable) – the additional validators for field
- default (instance of value_types) – the default value of the field
-
class
flyforms.fields.
IntField
(min_value=None, max_value=None, **kwargs)[source]¶ Reflects Python
int
valuesParameters: - required (bool) – boolean flag is this field required
- null (bool) – boolean flag is field value may be
None
- min_value – the minimum valid value
- max_value – the maximum valid value
- choices (iterable) – iterable object contains possible values of this field
- validators (list of callable) – the additional validators for field
- default (instance of value_types) – the default value of the field
-
class
flyforms.fields.
FloatField
(min_value=None, max_value=None, **kwargs)[source]¶ Reflects Python
float
valuesParameters: - required (bool) – boolean flag is this field required
- null (bool) – boolean flag is field value may be
None
- min_value – the minimum valid value
- max_value – the maximum valid value
- choices (iterable) – iterable object contains possible values of this field
- validators (list of callable) – the additional validators for field
- default (instance of value_types) – the default value of the field
-
class
flyforms.fields.
ListField
(jsonify=True, **kwargs)[source]¶ Reflects iterable Python objects
Parameters: - required (bool) – boolean flag is this field required or may be
UNSET
- null (bool) – boolean flag is field value may be
None
- min_length (int) – minimum iterable length
- max_length (int) – maximum iterable length
- item_validators (list of Callable) – the additional validators for every item
- jsonify (bool) – if True all items should be one of
jsonify_types
- validators (list of callable) – the additional validators for field
- default (instance of value_types) – the default value of the field
- required (bool) – boolean flag is this field required or may be
Usage
# coding=utf-8
from flyforms.form import Form
from flyforms.fields import ListField
from flyforms.common import UNSET
class ListForm(Form):
jsonify_list = ListField(min_length=2, max_length=5)
common_list = ListField(min_length=3, jsonify=False)
if __name__ == '__main__':
form = ListForm(
jsonify_list=["Hello!", 2.5, 0],
common_list=[object(), 500, "... world!", UNSET]
)
print(form.is_valid) # >>> True
print(form.errors) # >>> {}
-
class
flyforms.fields.
ArrayField
(item_type, jsonify=True, **kwargs)[source]¶ New in version 0.2.0.
Reflects iterable objects where each item same type
Parameters: - item_type – type of each item in the list
- required (bool) – boolean flag is this field required or may be
UNSET
- null (bool) – boolean flag is field value may be
None
- min_length (int) – minimum iterable length
- max_length (int) – maximum iterable length
- item_validators (list of Callable) – the additional validators for every item
- jsonify (bool) – if True all items should be one of
jsonify_types
- validators (list of callable) – the additional validators for field
- default (instance of value_types) – the default value of the field
Usage
# ArrayField usage
from flyforms.form import Form
from flyforms.fields import StringField, ArrayField
class CommentForm(Form):
login = StringField()
comment = StringField(max_length=256)
tags = ArrayField(item_type=str)
if __name__ == '__main__':
f = CommentForm(
login="YourLogin",
comment="Your comment",
tags=["schema", "python", "json"] # <-- list
)
print(f.is_valid) # >>> True
print(f.errors) # >>> {}
print(f.to_python())
# Given list was wrapped into tuple
print(type(f.tags)) # >>> <type 'tuple'>
-
class
flyforms.fields.
DatetimeField
(required=True, fmt='%Y-%m-%d %H:%M:%S', now=False, null=False, validators=())[source]¶ New in version 0.3.0.
A datetime field.
Parse string contains datetime via datetime.strptime
Parameters:
-
class
flyforms.fields.
DictField
(schema, **kwargs)[source]¶ New in version 0.3.0.
Reflects Python dict
Parameters:
Usage
# DictField usage
from flyforms.form import Form
from flyforms.fields import DictField, EmailField, StringField
class MyForm(Form):
cred = DictField(
schema={
"email": EmailField(),
"password": StringField(
min_length=8,
regex=r"^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#\$%\^&\*])",
max_length=64
)
}
)
if __name__ == '__main__':
f = MyForm(
cred={
"email": "qwerty@gmail.com",
"password": "Qwerty_#123"
} # <--- dict
)
print(f.is_valid) # >>> True
print(f.errors) # >>> {}
print(f.cred) # >>> {'password': 'Qwerty_#123', 'email': 'qwerty@gmail.com'}
print(type(f.cred)) # >>> <class 'flyforms.common.FrozenDict'> <--- !!!
Nested DictField usage
# DictField nested usage
from flyforms.form import Form
from flyforms.fields import DictField, ListField, StringField, EmailField
from pprint import pprint
class MyForm(Form):
field = DictField(
schema={
"list_field": ListField(),
"nested_dict": DictField(
schema={
"field1": EmailField(),
"field2": StringField(),
"nested_dd": DictField(
schema={
"email": EmailField(required=False)
}
)
}
)
}
)
if __name__ == '__main__':
f = MyForm(
field={
"list_field": [0, 1, "Hello world!"],
"nested_dict": {
"field1": "qwerty@qwerty.com",
"field2": "Hello world!",
"nested_dd": {
"email": "qwerty@qwerty.com"
}
}
}
)
print(f.is_valid) # >>> True
pprint(f.to_python())
Embedded Forms¶
Since version 1.0.0 FlyForms provides mechanism of encapsulation one Form to an other within EmbeddedFormField
.
Usage
# coding=utf-8
from flyforms.form import Form
from flyforms.fields import EmbeddedFormField, EmailField, StringField
class EmbeddedForm(Form):
email = EmailField()
password = StringField(
min_length=8,
regex=r"^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#\$%\^&\*])",
max_length=64
)
class ContainerForm(Form):
first_name = StringField(
regex=r"^[A-Z].*$",
min_length=3,
max_length=64
)
last_name = StringField(
regex=r"^[A-Z].*$",
min_length=3,
max_length=64
)
login_data = EmbeddedFormField(EmbeddedForm, null=True)
if __name__ == '__main__':
f = ContainerForm(**{
"first_name": "John",
"last_name": "Smith",
"login_data": {
"email": "smith@gmail.com",
"password": "Qw3rT!y_"
}
})
print(f.is_bound) # >>> True
print(f.is_valid) # >>> True
print(f.errors) # >>> {}
print(f.to_python())
print(f.login_data) # >>> {'password': 'Qw3rT!y_', 'email': 'smith@gmail.com'}
print(f.login_data.password) # >>> Qw3rT!y_
Custom Fields¶
Todo
finish
Validators¶
Generally, Validator is a callable object that validates given value with it`s internal logic.
If value is not valid ValidationError
will be raised.
-
class
flyforms.validators.
ValidationError
[source]¶ Raised when a validator fails to validate it’s input.
Validator class¶
All builtin Validators inherit Validator
or it`s subclass SimpleValidator
.
Builtin validators API¶
-
class
flyforms.validators.
TypeValidator
(value_types)[source]¶ Validates is given value instance of passed
value_types
Parameters: value_types – list of possible value types
-
class
flyforms.validators.
EntryValidator
(iterable, item_type=None)[source]¶ Validates is given value in specified during initialization iterable object
Parameters: iterable – the iterable object Raise: TypeError if given object is not iterable
-
class
flyforms.validators.
MinValueValidator
(min_value, strong=True)[source]¶ Validates is given value greater than specified during initialization value
Parameters: - min_value – the minimum valid value
- strong (bool) – boolean flag should be comparison strict or not
-
class
flyforms.validators.
MaxValueValidator
(max_value, strong=True)[source]¶ Validates is given value less than specified during initialization value
Parameters: - max_value – the maximum valid value
- strong (bool) – boolean flag should be comparison strict or not
-
class
flyforms.validators.
MinLengthValidator
(min_length, strong=True)[source]¶ Validates the minimum object length
Parameters: - min_length – the minimum valid length
- strong (bool) – boolean flag should be comparison strict or not
-
class
flyforms.validators.
MaxLengthValidator
(max_length, strong=True)[source]¶ Validates the maximum object length
Parameters: - max_length – the maximum valid length
- strong (bool) – boolean flag should be comparison strict or not