Skip to main content

a wrapper of marshmallow for form library like behavior

Project description


form library is not validation library

What is form library?

  • anyone says, ‘it is validation library for post/get data’
  • another says, ‘it is rendering library for form element’

marshmallow-form is not above one. form library is ‘a container for presentation metadata’. so, form object is just a container.

  • ‘rendering form element’, it is a task of template library(mako, jinja2, …).
  • ‘validation post/get data’, it is a task of schema library(colander, marshmallow, …).

marshmallow-form is just a metadata container.


  • having metadata anywhere
  • nested field support
  • accessing schema
  • building your own form library

getting started


from pypi package repository.

# pip install marshmallow-form

from repository

git clone
cd marshmallow-form
python develop

form class definition

the way of form definition.

import marshmallow_form as mf

class PersonForm(mf.Form):
    name = mf.String(label="名前", placeholder="foo", widget="str")
    age = mf.Integer(label="年齢", placeholder="0", widget="int")

class ParentsForm(mf.Form):
    father = mf.Nested(PersonForm, label="父親")
    mother = mf.Nested(PersonForm, label="母親")
  • define form class with marshmallow_form.Form
  • using field classes, define form fields.
  • label and placeholder is metadata for presentation

with template library

with template library, form is just a metadata container. so, a above definition, using form as metadata container.

print(["label"]) # => '名前'  # 'name' in japanese
print(["placeholder"]) # => 'foo'
print( # => 'foo'
  • accessing metadata with __getitem__.
  • accessing initial data or passed data with .value

with template(mako). deciding rendering method, using widget metadata.

from mako.template import Template

template = Template("""
<%def name="field(f)">\
  ${getattr(self, "field_" + f["widget"])(f)}

<%def name="field_str(f)">\
  <input type="text" name="${}" value="${f.value}" placeholder="${f["placeholder"]}"/>

<%def name="field_int(f)">\
  <input type="number" name="${}" value="${f.value}" placeholder="${f["placeholder"]}"/>

<form action="#" method="POST">
%for f in form:



<form action="#" method="POST">
    <input type="text" name="" value="" placeholder="foo"/>
    <input type="number" name="father.age" value="0" placeholder="0"/>
    <input type="text" name="" value="" placeholder="foo"/>
    <input type="number" name="mother.age" value="0" placeholder="0"/>


from marshmallow.validate import Length
from marshmallow import ValidationError

class MLength(Length):
    message_min = 'Too short! {min}.'
    message_max = 'Too long! {max}.'

class AuthenticationForm(mf.Form):
    name = mf.String()
    password = mf.String(validate=MLength(5))
    password_confirm = mf.String()

    def same(schema, data):
        if data["password"] != data["password_confirm"]:
            raise ValidationError("not same!", "password")

input_data = {"name": "foo", "password": "*", "password_confirm": "+"}
form = AuthenticationForm(input_data)
print(form.validate())  # False
print(form.errors) # {'password': ['Too short! 5.', 'not same!']}
{'password': ['Too short! 5.', 'not same!']}


having metadata anywhere

  • form metadata
  • field metadata
  • metadata inheritance
  • metadata override

form metadata

import marshmallow_form as mf

class MyForm(mf.Form):
    name = mf.Str()

    class Meta:
        metadata = {"action": "#"}

form = MyForm()
form["action"]  # => #
form.metadata["method"] = "post"
form["method"]  # => "post"

MyForm()["method"]  # => ""

field metadata

class MyForm2(mf.Form):
    name = mf.Str()
    ctime = mf.DateTime(disable=True)

form = MyForm2()
form.ctime["disable"]  # => True

metadata inheritance

from functools import partial
DateTime = partial(mf.DateTime, widget="tdcalendar")

class MyForm3(mf.Form):
    ctime = DateTime()
    utime = DateTime()

form = MyForm3()
form.ctime["widget"]  # => "tdcalendar"
form.utime["widget"]  # => "tdcalendar"

metadata override

class MyForm4(MyForm3):
    class Meta:
        overrides = {"ctime": {"widget": "mycalendar"}}

form = MyForm4()
form.ctime["widget"]  # => "mycalendar"
form.utime["widget"]  # => "tdcalendar"

or with nested

class PersonForm(mf.Form):
    name = mf.String(label="名前", placeholder="foo", widget="str")
    age = mf.Integer(label="年齢", placeholder="0", widget="int")

class ParentsForm(mf.Form):
    father = mf.Nested(PersonForm, label="父親", overrides={"name": {"label": "父親の名前"}})
    mother = mf.Nested(PersonForm, label="母親")

form = ParentsForm()
form.father["label"]  # => "父親"["label"]  # => "父親の名前"["label"]  # => "名前"

dynamic form

  • modify field
  • add field
  • remove field

modify field

form = StudentForm()
form.color.metadata["pairs"] = [("red", "red"), ("blue", "blue")]
form.color["pairs"]  # => [('red', 'red'), ('blue', 'blue')]

add field

class StudentForm(mf.Form):
    color = mf.Select([])
    name = mf.Str()

form = StudentForm(initial={"grade": 3})
form.add_field("grade", mf.Int(label="学年"))
form.grade.value  # => 3
form.grade["label"]  # => "学年"

[ for f in form]  # => ['color', 'name', 'grade']

remove field

form = StudentForm()

[ for f in form]  # => ['name']

accessing schema

  • schema class
  • schema instance

schema class

from collections import namedtuple
Person = namedtuple("Person", "name age")

class PersonForm(mf.Form):
    name = mf.Str()
    age = mf.Int()

    def make_object(self, data):
        return Person(**data)

PersonForm.Schema  # => <class 'marshmallow.schema.PersonSchema'>

schema = PersonForm.Schema(many=True)
schema.dump([Person("foo", 20), Person("bar", 20)]).data
# => OrderedDict([('name', 'foo'), ('age', 20)]), OrderedDict([('name', 'bar'), ('age', 20)])

schema instance

form = PersonForm()
form.schema.load({"name": "foo", "age": 20}).data  # => Person(name='foo', age=20)

building your own form library

  • define your form field class
  • define the way of rendering

define your form field class

if just only adding default metadata, using functools.partial.

import functools
PositiveInt = functools.partial(mf.Int, validate=lambda x: x > 0)

class Form(mf.Form):
    x = PositiveInt()

print(Form({"x": "-10"}).load())
# UnmarshalResult(data=OrderedDict([('x', None)]), errors={'x': ['Validator <lambda>(-10) is False']})

if define your own field class

from marshmallow.fields import Field
from marshmallow.exceptions import UnmarshallingError
import base64

class Base64(Field):
    """ tiny base64 field"""
    def __init__(self, *args, **kwargs):
        super(Base64, self).__init__(*args, **kwargs)

    def _serialize(self, value, attr, obj):
        return base64.encodebytes(value)

    def _deserialize(self, value):
            return base64.decodebytes(value.encode("utf-8"))
            raise UnmarshallingError("oops")

MyBase64 = mf.field_factory(Base64)

class Form(mf.Form):
    x = MyBase64(label="this is broken")

form = Form({"x": "MTEx"})
# UnmarshalResult(data=OrderedDict([('x', b'111')]), errors={})

define the way of rendering

def input(field, placeholder=""):
    fmt = '<input name="{name}" value="{value}" placeholder="{placeholder}">'
    return fmt.format(name=field["name"], value=field.value, placeholder=placeholder)

class Form(mf.Form):
    name = mf.Str(__call__=input)

form = Form()
# => <input name="" value="" placeholder="foo">

Project details

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Files for marshmallow-form, version 0.1
Filename, size File type Python version Upload date Hashes
Filename, size marshmallow-form-0.1.tar.gz (14.2 kB) File type Source Python version None Upload date Hashes View

Supported by

AWS AWS Cloud computing Datadog Datadog Monitoring DigiCert DigiCert EV certificate Facebook / Instagram Facebook / Instagram PSF Sponsor Fastly Fastly CDN Google Google Object Storage and Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Salesforce Salesforce PSF Sponsor Sentry Sentry Error logging StatusPage StatusPage Status page