{ "info": { "author": "podhmo", "author_email": "UNKNOWN", "bugtrack_url": null, "classifiers": [ "Programming Language :: Python", "Programming Language :: Python :: Implementation :: CPython" ], "description": "marshmallow-form\n========================================\n\nmotivation\n----------------------------------------\n\nform library is not validation library\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nWhat is form library?\n\n- anyone says, 'it is validation library for post/get data'\n- another says, 'it is rendering library for form element'\n\nmarshmallow-form is not above one.\nform library is 'a container for presentation metadata'. so, form object is just a container.\n\n- 'rendering form element', it is a task of template library(mako, jinja2, ...).\n- 'validation post/get data', it is a task of schema library(colander, marshmallow, ...).\n\nmarshmallow-form is just a metadata container.\n\nfeatures\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n- having metadata anywhere\n- nested field support\n- accessing schema\n- building your own form library\n\n\ngetting started\n----------------------------------------\n\ninstall\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nfrom pypi package repository.\n\n::\n\n # pip install marshmallow-form\n\nfrom repository\n\n::\n\n git clone git@github.com/podhmo/marshmallow-form.git\n cd marshmallow-form\n python setup.py develop\n\n\nform class definition\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nthe way of form definition.\n\n.. code-block:: python\n\n import marshmallow_form as mf\n\n\n class PersonForm(mf.Form):\n name = mf.String(label=\"\u540d\u524d\", placeholder=\"foo\", widget=\"str\")\n age = mf.Integer(label=\"\u5e74\u9f62\", placeholder=\"0\", widget=\"int\")\n\n\n class ParentsForm(mf.Form):\n father = mf.Nested(PersonForm, label=\"\u7236\u89aa\")\n mother = mf.Nested(PersonForm, label=\"\u6bcd\u89aa\")\n\n- define form class with marshmallow_form.Form\n- using field classes, define form fields.\n- label and placeholder is metadata for presentation\n\n\nwith template library\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nwith template library, form is just a metadata container.\nso, a above definition, using form as metadata container.\n\n\n.. code-block:: python\n\n print(form.father.name[\"label\"]) # => '\u540d\u524d' # 'name' in japanese\n print(form.father.name[\"placeholder\"]) # => 'foo'\n print(form.name.value) # => 'foo'\n\n- accessing metadata with `__getitem__`.\n- accessing initial data or passed data with `.value`\n\n\nwith template(mako). deciding rendering method, using `widget` metadata.\n\n.. code-block:: python\n\n from mako.template import Template\n\n template = Template(\"\"\"\n <%def name=\"field(f)\">\\\n ${getattr(self, \"field_\" + f[\"widget\"])(f)}\n \n\n <%def name=\"field_str(f)\">\\\n \n \n\n <%def name=\"field_int(f)\">\\\n \n \n\n
\n %for f in form:\n ${field(f)}\n %endfor\n
\n \"\"\")\n\n print(template.render(form=form))\n\noutput.\n\n.. code-block:: html\n\n
\n \n \n \n \n
\n\nvalidation\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n.. code-block:: python\n\n from marshmallow.validate import Length\n from marshmallow import ValidationError\n\n\n class MLength(Length):\n message_min = 'Too short! {min}.'\n message_max = 'Too long! {max}.'\n\n\n class AuthenticationForm(mf.Form):\n name = mf.String()\n password = mf.String(validate=MLength(5))\n password_confirm = mf.String()\n\n @mf.Form.validator\n def same(schema, data):\n if data[\"password\"] != data[\"password_confirm\"]:\n raise ValidationError(\"not same!\", \"password\")\n\n\n input_data = {\"name\": \"foo\", \"password\": \"*\", \"password_confirm\": \"+\"}\n form = AuthenticationForm(input_data)\n print(form.validate()) # False\n print(form.errors) # {'password': ['Too short! 5.', 'not same!']}\n {'password': ['Too short! 5.', 'not same!']}\n\n\ndetail\n----------------------------------------\n\nhaving metadata anywhere\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n- form metadata\n- field metadata\n- metadata inheritance\n- metadata override\n\nform metadata\n\n.. code-block:: python\n\n import marshmallow_form as mf\n\n\n class MyForm(mf.Form):\n name = mf.Str()\n\n class Meta:\n metadata = {\"action\": \"#\"}\n\n form = MyForm()\n form[\"action\"] # => #\n form.metadata[\"method\"] = \"post\"\n form[\"method\"] # => \"post\"\n\n MyForm()[\"method\"] # => \"\"\n\n\nfield metadata\n\n.. code-block:: python\n\n class MyForm2(mf.Form):\n name = mf.Str()\n ctime = mf.DateTime(disable=True)\n\n\n form = MyForm2()\n form.ctime[\"disable\"] # => True\n\nmetadata inheritance\n\n.. code-block:: python\n\n from functools import partial\n DateTime = partial(mf.DateTime, widget=\"tdcalendar\")\n\n\n class MyForm3(mf.Form):\n ctime = DateTime()\n utime = DateTime()\n\n form = MyForm3()\n form.ctime[\"widget\"] # => \"tdcalendar\"\n form.utime[\"widget\"] # => \"tdcalendar\"\n\nmetadata override\n\n.. code-block:: python\n\n class MyForm4(MyForm3):\n class Meta:\n overrides = {\"ctime\": {\"widget\": \"mycalendar\"}}\n\n\n form = MyForm4()\n form.ctime[\"widget\"] # => \"mycalendar\"\n form.utime[\"widget\"] # => \"tdcalendar\"\n\nor with nested\n\n.. code-block:: python\n\n class PersonForm(mf.Form):\n name = mf.String(label=\"\u540d\u524d\", placeholder=\"foo\", widget=\"str\")\n age = mf.Integer(label=\"\u5e74\u9f62\", placeholder=\"0\", widget=\"int\")\n\n\n class ParentsForm(mf.Form):\n father = mf.Nested(PersonForm, label=\"\u7236\u89aa\", overrides={\"name\": {\"label\": \"\u7236\u89aa\u306e\u540d\u524d\"}})\n mother = mf.Nested(PersonForm, label=\"\u6bcd\u89aa\")\n\n form = ParentsForm()\n form.father[\"label\"] # => \"\u7236\u89aa\"\n form.father.name[\"label\"] # => \"\u7236\u89aa\u306e\u540d\u524d\"\n form.mother.name[\"label\"] # => \"\u540d\u524d\"\n\n\ndynamic form\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n- modify field\n- add field\n- remove field\n\nmodify field\n\n.. code-block:: python\n\n form = StudentForm()\n form.color.metadata[\"pairs\"] = [(\"red\", \"red\"), (\"blue\", \"blue\")]\n form.color[\"pairs\"] # => [('red', 'red'), ('blue', 'blue')]\n\n\nadd field\n\n.. code-block:: python\n\n class StudentForm(mf.Form):\n color = mf.Select([])\n name = mf.Str()\n\n form = StudentForm(initial={\"grade\": 3})\n form.add_field(\"grade\", mf.Int(label=\"\u5b66\u5e74\"))\n form.grade.value # => 3\n form.grade[\"label\"] # => \"\u5b66\u5e74\"\n\n [f.name for f in form] # => ['color', 'name', 'grade']\n\nremove field\n\n.. code-block:: python\n\n form = StudentForm()\n form.remove_field(\"color\")\n\n [f.name for f in form] # => ['name']\n\n\n\naccessing schema\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n- schema class\n- schema instance\n\nschema class\n\n.. code-block:: python\n\n from collections import namedtuple\n Person = namedtuple(\"Person\", \"name age\")\n\n\n class PersonForm(mf.Form):\n name = mf.Str()\n age = mf.Int()\n\n def make_object(self, data):\n return Person(**data)\n\n PersonForm.Schema # => \n\n schema = PersonForm.Schema(many=True)\n schema.dump([Person(\"foo\", 20), Person(\"bar\", 20)]).data\n # => OrderedDict([('name', 'foo'), ('age', 20)]), OrderedDict([('name', 'bar'), ('age', 20)])\n\nschema instance\n\n.. code-block:: python\n\n form = PersonForm()\n form.schema.load({\"name\": \"foo\", \"age\": 20}).data # => Person(name='foo', age=20)\n\n\nbuilding your own form library\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n- define your form field class\n- define the way of rendering\n\ndefine your form field class\n\nif just only adding default metadata, using functools.partial.\n\n.. code-block:: python\n\n import functools\n PositiveInt = functools.partial(mf.Int, validate=lambda x: x > 0)\n\n class Form(mf.Form):\n x = PositiveInt()\n\n print(Form({\"x\": \"-10\"}).load())\n # UnmarshalResult(data=OrderedDict([('x', None)]), errors={'x': ['Validator (-10) is False']})\n\nif define your own field class\n\n.. code-block:: python\n\n from marshmallow.fields import Field\n from marshmallow.exceptions import UnmarshallingError\n import base64\n\n\n class Base64(Field):\n \"\"\" tiny base64 field\"\"\"\n def __init__(self, *args, **kwargs):\n super(Base64, self).__init__(*args, **kwargs)\n\n def _serialize(self, value, attr, obj):\n return base64.encodebytes(value)\n\n def _deserialize(self, value):\n try:\n return base64.decodebytes(value.encode(\"utf-8\"))\n except:\n raise UnmarshallingError(\"oops\")\n\n MyBase64 = mf.field_factory(Base64)\n\n\n class Form(mf.Form):\n x = MyBase64(label=\"this is broken\")\n\n form = Form({\"x\": \"MTEx\"})\n print(form.load())\n # UnmarshalResult(data=OrderedDict([('x', b'111')]), errors={})\n\ndefine the way of rendering\n\n.. code-block:: python\n\n def input(field, placeholder=\"\"):\n fmt = ''\n return fmt.format(name=field[\"name\"], value=field.value, placeholder=placeholder)\n\n\n class Form(mf.Form):\n name = mf.Str(__call__=input)\n\n form = Form()\n print(form.name(placeholder=\"foo\"))\n # => ", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/podhmo/marshmallow-form", "keywords": "marshmallow,form", "license": "UNKNOWN", "maintainer": null, "maintainer_email": null, "name": "marshmallow-form", "package_url": "https://pypi.org/project/marshmallow-form/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/marshmallow-form/", "project_urls": { "Download": "UNKNOWN", "Homepage": "https://github.com/podhmo/marshmallow-form" }, "release_url": "https://pypi.org/project/marshmallow-form/0.1.1/", "requires_dist": null, "requires_python": null, "summary": "a wrapper of marshmallow for form library like behavior", "version": "0.1.1" }, "last_serial": 1531323, "releases": { "0.1": [ { "comment_text": "", "digests": { "md5": "895badcedd3c0c637b67f4354048abe2", "sha256": "4eb3a09b82e90485dc8ec1b8a1ba0933bb87235e6274bd7ca9154a0139fcc8a2" }, "downloads": -1, "filename": "marshmallow-form-0.1.tar.gz", "has_sig": false, "md5_digest": "895badcedd3c0c637b67f4354048abe2", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14241, "upload_time": "2015-03-30T14:28:59", "url": "https://files.pythonhosted.org/packages/b0/2a/320c24df9bfdc4c4fa1da47c02a80b66ed9676beddc00adc13effa24b67b/marshmallow-form-0.1.tar.gz" } ], "0.1.1": [ { "comment_text": "", "digests": { "md5": "a9004bf1baec9c69b1e9c9e1d55be74f", "sha256": "aca64f216486eca357369c7e0f657f361fffc58953792714eeb407708d473f74" }, "downloads": -1, "filename": "marshmallow-form-0.1.1.tar.gz", "has_sig": false, "md5_digest": "a9004bf1baec9c69b1e9c9e1d55be74f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14998, "upload_time": "2015-05-03T10:15:43", "url": "https://files.pythonhosted.org/packages/ca/e5/044b27fe396c2dca92fc6af1fc9666fc923f1481ff4cd6b36c01a096b365/marshmallow-form-0.1.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "a9004bf1baec9c69b1e9c9e1d55be74f", "sha256": "aca64f216486eca357369c7e0f657f361fffc58953792714eeb407708d473f74" }, "downloads": -1, "filename": "marshmallow-form-0.1.1.tar.gz", "has_sig": false, "md5_digest": "a9004bf1baec9c69b1e9c9e1d55be74f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14998, "upload_time": "2015-05-03T10:15:43", "url": "https://files.pythonhosted.org/packages/ca/e5/044b27fe396c2dca92fc6af1fc9666fc923f1481ff4cd6b36c01a096b365/marshmallow-form-0.1.1.tar.gz" } ] }