Forms
Model utilities for Air.
Provides a thin wrapper around :class:pydantic.BaseModel that knows how to
generate matching :class:air.forms.AirForm subclasses on demand.
AirModel
Bases: BaseModel
Base class for models that integrate tightly with Air forms.
to_form
classmethod
to_form(*, name=None, includes=None, widget=None)
Return an :class:AirForm instance bound to cls.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str | None
|
Optional explicit class name for the generated form. |
None
|
includes
|
Sequence[str] | None
|
Optional iterable of field names to render (defaults to all fields). |
None
|
widget
|
Callable | None
|
Optional custom rendering callable. |
None
|
Returns:
| Type | Description |
|---|---|
AirForm
|
An instance of :class: |
Example:
from collections.abc import Sequence
from pydantic import BaseModel
import air
from air.forms import default_form_widget
app = air.Air()
class ContactModel(air.AirModel):
name: str
email: str
phone: str | None = None
def custom_widget(
model: type[BaseModel],
data: dict | None = None,
errors: list | None = None,
includes: Sequence[str] | None = None,
) -> air.Div:
return air.Div(
air.P("Custom form styling:"),
air.Raw(default_form_widget(model, data, errors, includes)),
class_="custom-form",
)
def get_contact_form() -> air.AirForm:
return ContactModel.to_form(
name="CustomContactForm", # Custom form class name
includes=["name", "email"], # Only render these fields
widget=custom_widget, # Custom rendering function
)
@app.page
def index() -> air.Html:
contact_form = get_contact_form()
return air.Html(
air.H1("Contact Form"),
air.P("This form demonstrates name, includes, and widget parameters"),
air.Form(
contact_form.render(),
air.Button("Submit", type="submit"),
method="post",
action="/submit",
),
)
@app.post("/submit")
async def submit(request: air.Request) -> air.Html:
form_data = await request.form()
contact_form = get_contact_form()
if contact_form.validate(form_data):
return air.Html(
air.H1("Success"),
air.P(f"Name: {contact_form.data.name}"),
air.P(f"Email: {contact_form.data.email}"),
)
return air.Html(
air.H1("Error"),
air.P(f"Errors: {len(contact_form.errors or [])}"),
)
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="127.0.0.1", port=8000)
Source code in src/air/models.py
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | |