Skip to main content

AirForm

PyPI version

Pydantic-native form validation and rendering for Air. Define an AirModel, get a validated, rendered HTML form with CSRF protection.

Features

  • Type-safe validated data via AirForm[MyModel] generic parameter
  • Works with AirModel (database-backed forms) and plain BaseModel (contact forms, search, etc.)
  • Reads the full AirField metadata vocabulary: Widget, Label, Placeholder, HelpText, Choices, Autofocus, PrimaryKey, Hidden, ReadOnly
  • Auto-skips PrimaryKey and Hidden("form") fields in rendered output
  • HTML5 validation attributes from Pydantic constraints (minlength, maxlength, required)
  • Accessible by default: aria-invalid, aria-describedby, role="alert" on errors
  • Textarea, select, and checkbox rendering from type annotations and metadata
  • Zero-config CSRF protection: render() embeds a signed token, validate() checks it
  • Scoped excludes: hide fields from display, saving, or both
  • save_data() returns a dict ready for await MyModel.create()
  • default_css() built-in stylesheet for polished forms without a CSS framework
  • Swappable widget for custom renderers
  • from_request() for async ASGI request handling (works with FastAPI Depends)

Quick start

Database-backed form (most common)

from airmodel import AirModel, AirField
from airform import AirForm
import air

app = air.Air()

class BookOrder(AirModel):
    id: int | None = AirField(default=None, primary_key=True)
    title: str = AirField(label="Book Title", min_length=1)
    quantity: int = AirField(label="Quantity")

class BookOrderForm(AirForm[BookOrder]):
    pass

@app.page
def order_page(request: air.Request):
    return air.Html(
        air.H1("Order a Book"),
        air.Form(
            BookOrderForm().render(),
            air.Button("Order", type_="submit"),
            method="post", action="/order",
        ),
    )

@app.post("/order")
async def submit_order(request: air.Request):
    form = await BookOrderForm.from_request(request)
    if form.is_valid:
        await BookOrder.create(**form.save_data())
        return air.Html(air.H1(f"Ordered: {form.data.title}"))
    return air.Html(
        air.Form(
            form.render(),
            air.Button("Order", type_="submit"),
            method="post", action="/order",
        ),
    )

Plain form (no database)

from pydantic import BaseModel
from airfield import AirField
from airform import AirForm

class ContactMessage(BaseModel):
    name: str = AirField(label="Name", autofocus=True)
    email: str = AirField(type="email", label="Email")
    message: str = AirField(widget="textarea", label="Message")

class ContactForm(AirForm[ContactMessage]):
    pass

form = ContactForm()
form.validate({"name": "Audrey", "email": "audreyfeldroy@example.com", "message": "Hello!"})
if form.is_valid:
    send_email(form.data.name, form.data.email, form.data.message)

html = ContactForm().render()

Documentation

Documentation is built with Zensical and deployed to GitHub Pages.

API documentation is auto-generated from docstrings using mkdocstrings.

Docs deploy automatically on push to main via GitHub Actions. To enable this, go to your repo's Settings > Pages and set the source to GitHub Actions.

Installation

uv add AirForm

CLI

Preview rendered form HTML from any Pydantic model:

airform preview myapp.models:ContactModel

Development

See CONTRIBUTING.md for setup instructions.

Author

AirForm was created in 2026 by Audrey M. Roy Greenfeld, extending Daniel Roy Greenfeld's original form rendering design from Air.

Built with Cookiecutter and the audreyfeldroy/cookiecutter-pypackage project template.

Release files for AirForm 0.5.0

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

Source distribution (sdist)

Source distribution for AirForm 0.5.0
File Size Uploaded
airform-0.5.0.tar.gz 79.4 kB Details

Built distribution (wheel)

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

Total release size: 93.8 kB

Release files / airform-0.5.0.tar.gz

Download URL airform-0.5.0.tar.gz
Size 79.4 kB
Tags Source
SHA-256 checksum
How to use checksums
fb68d6f67076cd5c1ae30b1bcabadb9d757b2458627d69c72047fddc5f45151d
BLAKE2b-256 checksum
How to use checksums
be33b21aeb35785c4f90e1384a2f7028ad5b76f9add9a2390fe043180be9676b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 21, 2026.

Transparency log

Release files / airform-0.5.0-py3-none-any.whl

Download URL airform-0.5.0-py3-none-any.whl
Size 14.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9eb94d5ab42573d8c7efef6c4c6c0ca0a1b0423207e3ff46543fcd0b4e97d7f1
BLAKE2b-256 checksum
How to use checksums
e062f849566051b3fc03d73ff10ad773378fc5354d1217ccaba78f6fd5830a8e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 21, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.5.0 This release

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.0

2 release files

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