Skip to main content
Archived

This project has been archived by its maintainers, and is no longer receiving any updates.

Fodantic

Pydantic-based HTTP forms.

Pydantic is the most widely used data validation library for Python, but it's hard to use it with regular HTTP forms... until now.

Fodantic allow you to quickly wrap your Pydantic models and use them as forms: with support for multiple values, checkboxes, error handling, and integration with your favorite ORM.

A simple example

from fodantic import formable
from pydantic import BaseModel

@formable
class UserModel(BaseModel):
    name: str
    friends: list[int]
    active: bool = True

# This is just an example. Here you would use the
# request POST data of your web framework instead.
# For example, for Flask: `request_data = request.form`
from multidict import MultiDict
request_data = MultiDict([
  ("name", "John Doe"),
  ("friends", "2"),
  ("friends", "3"),
])

# The magic
form = UserModel.as_form(request_data, object=None)

print(form)
#> UserModel.as_form(name='John Doe', friends=[2, 3], active=False)
print(form.fields["name"].value)
#> John Doe
print(form.fields["name"].error)
#> None
print(form.save())  # Can also update the `object` passed as an argument
#> {'name': 'John Doe', 'friends': [2, 3], 'active': False}

Installation

pip install fodantic

Requirements

  • Python > 3.10
  • Pydantic 2.*

Form Fields Parsing with Nested Notation

Fodantic supports parsing nested form fields using bracket ([]) notation -- similar to how Ruby on Rails and PHP handle form data. This allows you to easily create complex nested data structures from flat form submissions.

Nested Object Notation

You can use brackets to define nested objects in your form fields:

<input name="user[name]" value="Alice">
<input name="user[email]" value="alice@example.com">
<input name="user[address][city]" value="New York">
<input name="user[address][zip]" value="10001">

This will be parsed into a nested structure:

{
    "user": {
        "name": "Alice",
        "email": "alice@example.com",
        "address": {
            "city": "New York",
            "zip": "10001"
        }
    }
}

Array Notation

You can create arrays using numeric indexes or empty brackets:

Indexed Arrays

<input name="contacts[0][name]" value="John">
<input name="contacts[0][phone]" value="555-1234">
<input name="contacts[1][name]" value="Jane">
<input name="contacts[1][phone]" value="555-5678">

This will be parsed into:

{
  "contacts": [
    {"name": "John", "phone": "555-1234"},
    {"name": "Jane", "phone": "555-5678"},
  ]
}

Array Append (Empty Brackets)

<input name="tags[]" value="important">
<input name="tags[]" value="urgent">
<input name="tags[]" value="follow-up">

This will be parsed into:

{
  "tags": ["important", "urgent", "follow-up"]
}

Mixed Structures

You can combine these notations to create complex data structures:

<input name="user[name]" value="Bob">
<input name="user[skills][]" value="Python">
<input name="user[skills][]" value="JavaScript">
<input name="user[projects][0][name]" value="Project A">
<input name="user[projects][0][status]" value="active">
<input name="user[projects][1][name]" value="Project B">
<input name="user[projects][1][status]" value="pending">

This will be parsed into:

{
    "user": {
        "name": "Bob",
        "skills": ["Python", "JavaScript"],
        "projects": [
            {"name": "Project A", "status": "active"},
            {"name": "Project B", "status": "pending"}
        ]
    }
}

Usage with Pydantic Models

This nested notation works seamlessly with Pydantic models, allowing you to map complex form structures to nested models:

from fodantic import formable
from pydantic import BaseModel
from typing import List

class Address(BaseModel):
    city: str
    zip: str

class Project(BaseModel):
    name: str
    status: str

@formable
class UserModel(BaseModel):
    name: str
    skills: List[str] = []
    address: Address
    projects: List[Project] = []

# Your form data with nested structure
form = UserModel.as_form(request_data)

The parser handles all the complexity of transforming the flat form structure into the nested objects your models expect.

Booleans fields

Boolean fields are treated special because of how browsers handle checkboxes:

  • If not checked: the browser doesn't send the field at all, so the missing field will be interpreted as False.
  • If checked: It sends the "value" attribute, but this is optional, so it could send an empty string instead. So any value other than None will be interpreted as True.

Release files for fodantic 0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for fodantic 0.1
File Size Uploaded
fodantic-0.1.tar.gz 14.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for fodantic 0.1
File Interpreter ABI Platform
fodantic-0.1-py3-none-any.whl Python 3 none any Details

Total release size: 23.3 kB

Release files / fodantic-0.1.tar.gz

Download URL fodantic-0.1.tar.gz
Size 14.0 kB
Tags Source
SHA-256 checksum
How to use checksums
e1e22d5bf4ca208e370623cb4f24f712c66d1e80b088a1b91d6b95f792f1515f
BLAKE2b-256 checksum
How to use checksums
83b6d1173ae51ab076cea8566c2151038ba109d89ec595f3dbcb59cefd0ef428
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.7.9

Release files / fodantic-0.1-py3-none-any.whl

Download URL fodantic-0.1-py3-none-any.whl
Size 9.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
01da47dce34434625958034aaccf7f84c00919e42143dcd183c4f21431d7e1b9
BLAKE2b-256 checksum
How to use checksums
5dce28b53bbbb5bb06f1c59162f19364f34c3a1d1da1c61c4340853a2a10dd96
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.7.9
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page