Rendering API¶
The functions and methods that turn a model into HTML and a submission into data. Everything is imported from the top-level package.
render_form_html()¶
render_form_html(Model, form_data=None, errors=None, framework="bootstrap", *, submit_url, ...) -> str
Returns the form as an HTML string: the <form> element with its fields,
error summary and submit button, plus the small scripts and styles the form's
inputs need. It is a fragment for your page, not a whole page.
| Argument | Default | Effect |
|---|---|---|
submit_url |
required | The form's action. Never guessed. |
form_data |
None |
Values to show. None starts from the field defaults; a dict is used as is (see Fields and Inputs). Nested dicts, Enum members and dates are fine. |
errors |
None |
Messages to show, shaped like the data: {"email": "..."}, {"address": {"city": "..."}}, "_errors" for the whole form |
framework |
"bootstrap" |
"bootstrap", "material" or "none"; see Styling |
material_variant |
None |
"outlined" (the default look) or "filled"; only affects framework="material". See Material Design 3 |
layout |
"vertical" |
See Layouts |
wizard_options |
None |
See Layouts |
method |
"POST" |
The form's method |
include_submit_button |
True |
False leaves the button out, for a form you submit some other way |
csrf_mode |
"off" |
"required-provider" adds a hidden CSRF field; see CSRF Protection |
csrf_token_provider |
None |
The token, or a function returning it |
csrf_field_name |
"csrf_token" |
Name of the hidden CSRF field |
include_framework_assets |
False |
Add the framework's CSS and JavaScript to the output |
asset_mode |
"vendored" |
With assets included: "vendored" inlines the packaged files, "cdn" links pinned CDN copies |
self_contained |
False |
Shortcut for include_framework_assets=True with inlined files, Bootstrap Icons included; see Assets |
show_timing |
False |
Show how long rendering took under the form |
debug |
False |
Add a debug panel with the schema, data and errors |
enable_logging |
False |
Log rendering at DEBUG level; see Render Timing and Logging |
include_html_markers |
True |
Wrap the output in <!--- Start/End Pydantic-SchemaForms --> comments |
inject_layout_styles |
True |
Add the small stylesheet that makes the form fill its container |
Any other keyword becomes an attribute of the <form> tag, for example
id="signup" or **{"hx-post": "/signup"}. A form with a file input gets
enctype="multipart/form-data" unless you pass your own enctype.
render_form_html_async()¶
The same arguments and result as render_form_html(). It renders in a worker
thread so an async route doesn't block the event loop. Use it in FastAPI and
other async frameworks.
FormModel¶
FormModel is a Pydantic BaseModel with these class methods added:
| Method | Returns |
|---|---|
validate(data, *, submit_url=None, framework="bootstrap", **render_options) |
A ValidationResult. data is the raw request form (await request.form(), request.form) or a nested dict such as a JSON body. Render options (layout=, csrf_mode=, ...) are kept for render_with_errors(). |
render_form(data=None, errors=None, framework="bootstrap", *, submit_url, **options) |
The same as render_form_html(Model, ...) |
render_display(data, framework="bootstrap", *, layout="vertical", edit_urls=None, **options) |
Read-only HTML for validated data; see Show the answers back. data is result.data, a dict shaped like the model, or a model instance. options are the asset options plus material_variant and include_html_markers. |
as_api_model() |
A plain Pydantic model with the same fields and validation but without the form settings, for request bodies and response_model; see JSON API and JSON Schema |
get_pydantic_json_schema(**options) |
The standard JSON Schema, with sub-forms as $defs; Pydantic's model_json_schema() options pass through |
get_json_schema() |
The schema the renderer uses internally, form settings included |
The model's own model_config = {"title": "..."} titles the form's first
group in the grouped layouts.
ValidationResult¶
| Member | Holds |
|---|---|
is_valid |
True when everything passed |
data |
The validated values, nested like the model ({} when invalid) |
instance |
The validated model object (None when invalid) |
errors |
The messages, nested like the data; "_errors" holds form-wide ones |
error_list() |
The same errors as a flat list: [{"loc": ["pets", 1, "age"], "msg": "..."}] |
original_data |
The submission decoded into nested form, before validation |
render_with_errors(**options) |
The form again with the submitted values and the errors, using the options given to validate(). Pass errors= to show a different set, such as these merged with a FormValidator's. |
render_with_errors_async(**options) |
The same, off the event loop |
html() and SafeHTML¶
html(t"...") builds HTML from a Python 3.14 t-string and escapes every
interpolated value. Use it for anything you build around submitted data:
from pydantic_schemaforms import html
name = result.data["name"]
page = html(t"<p>Thanks, {name}!</p>")
It returns a SafeHTML, a str that html() won't escape again, so pieces
nest. Wrap a string in SafeHTML(...) only when it's HTML you trust, such as
another form you rendered.
Lower-level pieces¶
EnhancedFormRenderer(framework=..., include_framework_assets=..., asset_mode=...)is the renderer behindrender_form_html();.render_form_from_model(Model, data=None, errors=None, *, submit_url=..., ...)takes the same options. Reuse one instance to render many forms with the same settings.CSRFModeis the enum behindcsrf_mode(CSRFMode.REQUIRED_PROVIDER, ...).read_asset_text(path)returns a packaged asset, such as the vendored HTMX, for serving yourself; see Assets.parse_nested_form_data()andflatten_nested_data()convert between the input names (pets[0].name) and nested data, for tests that post raw form data.