Forms Reference

Module Summary

next.forms exposes form action registration, dispatch, formset helpers, frozen field and form specs, and a curated set of commonly used Django form fields and widgets. It also re-exports page from next.pages so that a single from next.forms import action, page covers the two most common decorators in a page.py.

API Tiers

next.forms groups its symbols into three tiers that describe the intended audience for each name. The lists below are representative. The autodoc blocks under Public API are the exhaustive surface.

Stable.

@action, page, Form, ModelForm, BaseForm, BaseModelForm, DForm, FormActionManager, form_action_manager, and the UID helpers (FORM_ACTION_REVERSE_NAME, URL_NAME_FORM_ACTION, redirect_to_origin). Use these in application code.

Advanced.

FormProvider, FormActionBackend, FormActionFactory, RegistryFormActionBackend, FormActionDispatch, FormActionOptions, ActionMeta, build_form_namespace_for_action, validated_next_form_page_path, the frozen specs (FieldSpec, FormsetSpec, FormSpec, FormSectionSpec, FormsetRowSpec, FieldKind), the spec helpers (field_spec, form_spec, formset_spec), the formset helper cleanup_extra_initial, and the signals and checks submodules. Use these when writing a custom backend or a form renderer. FormProvider auto-registers through the __init_subclass__ hook on RegisteredParameterProvider and resolves the bound form parameter, so application code never instantiates it.

Internal hooks.

Symbols with a leading underscore are implementation details re-exported for testing and advanced backend authoring. The full set lives in next.forms.__all__, which is the source of truth for the internal hook surface. Do not import these names in application code.

Public API

Decorator

next.forms.action(name: str, *, form_class: type[django_forms.Form] | Callable[..., type[django_forms.Form]] | None = None, namespace: str | None = None) Callable[[Callable[..., Any]], Callable[..., Any]][source]

Register a named form action. Names must be unique across the project.

Pass namespace=”app_label” to prefix the stored key with “app_label:”, which lets two apps use the same short name without colliding. Reverse is by the namespaced name.

form_class may be a Form subclass or a callable that returns one when called. Factory callables are dependency-resolved at dispatch time with the request and URL kwargs, which lets admin-style handlers shape the form per request (for example via ModelAdmin.get_form()).

Form Base Classes

class next.forms.Form(data=None, files=None, auto_id='id_%s', prefix=None, initial=None, error_class=<class 'django.forms.utils.ErrorList'>, label_suffix=None, empty_permitted=False, field_order=None, use_required_attribute=None, renderer=None, bound_field_class=None)[source]

A collection of fields with their associated data.

This extends Django’s Form with get_initial support.

base_fields = {}
declared_fields = {}
property media

Return all media required to render the widgets on this form.

class next.forms.ModelForm(data=None, files=None, auto_id='id_%s', prefix=None, initial=None, error_class=<class 'django.forms.utils.ErrorList'>, label_suffix=None, empty_permitted=False, instance=None, use_required_attribute=None, renderer=None)[source]

Form for editing a model instance.

This extends Django’s ModelForm with get_initial support.

base_fields = {}
declared_fields = {}
property media

Return all media required to render the widgets on this form.

class next.forms.BaseForm(data=None, files=None, auto_id='id_%s', prefix=None, initial=None, error_class=<class 'django.forms.utils.ErrorList'>, label_suffix=None, empty_permitted=False, field_order=None, use_required_attribute=None, renderer=None, bound_field_class=None)[source]

Custom BaseForm that extends Django’s BaseForm with get_initial.

classmethod get_initial() dict[str, Any][source]

Return initial data for this form.

Override this method to provide initial data. Subclasses can declare whichever DI parameters they need (request: HttpRequest, URL kwargs, or named dependencies). The dispatcher resolves them via the standard DI pipeline before invoking the override. The returned dictionary becomes the initial parameter passed to the form constructor.

class next.forms.BaseModelForm(data=None, files=None, auto_id='id_%s', prefix=None, initial=None, error_class=<class 'django.forms.utils.ErrorList'>, label_suffix=None, empty_permitted=False, instance=None, use_required_attribute=None, renderer=None)[source]

Custom BaseModelForm with get_initial support.

classmethod get_initial() dict[str, Any] | object[source]

Return initial data or a model instance for this form.

For ModelForm subclasses this may return either a dictionary, which becomes the initial parameter and results in a new instance on save, or a model instance, which becomes the instance parameter and updates the existing record. Subclasses may declare DI parameters in the override. The dispatcher resolves them automatically.

Fields and Widgets

The framework re-exports a curated set of commonly used Django form fields and widgets through next.forms so a single import covers most form definitions. Import any other Django field or widget directly from django.forms.

Custom BaseForm and BaseModelForm plus Django form-class re-exports.

BaseForm and BaseModelForm extend Django with get_initial, which lets @action resolve initial data from the request and URL kwargs before binding the form. Form and ModelForm apply the right metaclass so declarative field syntax continues to work. The Django form classes re-exported below are a convenience so user code can do from next.forms import CharField, EmailField without reaching into Django directly.

class next.forms.base.BooleanField(*, required=True, widget=None, label=None, initial=None, help_text='', error_messages=None, show_hidden_initial=False, validators=(), localize=False, disabled=False, label_suffix=None, template_name=None, bound_field_class=None)[source]
widget

alias of CheckboxInput

to_python(value)[source]

Return a Python boolean object.

validate(value)[source]
has_changed(initial, data)[source]

Return True if data differs from initial.

class next.forms.base.CharField(*, max_length=None, min_length=None, strip=True, empty_value='', **kwargs)[source]
__init__(*, max_length=None, min_length=None, strip=True, empty_value='', **kwargs)[source]
to_python(value)[source]

Return a string.

widget_attrs(widget)[source]

Given a Widget instance (not a Widget class), return a dictionary of any HTML attributes that should be added to the Widget, based on this Field.

class next.forms.base.CheckboxInput(attrs=None, check_test=None)[source]
input_type = 'checkbox'
template_name = 'django/forms/widgets/checkbox.html'
__init__(attrs=None, check_test=None)[source]
format_value(value)[source]

Only return the ‘value’ attribute if value isn’t empty.

get_context(name, value, attrs)[source]
value_from_datadict(data, files, name)[source]

Given a dictionary of data and this widget’s name, return the value of this widget or None if it’s not provided.

value_omitted_from_data(data, files, name)[source]
property media
class next.forms.base.ChoiceField(*, choices=(), **kwargs)[source]
widget

alias of Select

default_error_messages = {'invalid_choice': 'Select a valid choice. %(value)s is not one of the available choices.'}
__init__(*, choices=(), **kwargs)[source]
property choices
to_python(value)[source]

Return a string.

validate(value)[source]

Validate that the input is in self.choices.

valid_value(value)[source]

Check to see if the provided value is a valid choice.

class next.forms.base.DateField(*, input_formats=None, **kwargs)[source]
widget

alias of DateInput

input_formats = ['%Y-%m-%d', '%m/%d/%Y', '%m/%d/%y', '%b %d %Y', '%b %d, %Y', '%d %b %Y', '%d %b, %Y', '%B %d %Y', '%B %d, %Y', '%d %B %Y', '%d %B, %Y']
default_error_messages = {'invalid': 'Enter a valid date.'}
to_python(value)[source]

Validate that the input can be converted to a date. Return a Python datetime.date object.

strptime(value, format)[source]
class next.forms.base.DateInput(attrs=None, format=None)[source]
format_key = 'DATE_INPUT_FORMATS'
template_name = 'django/forms/widgets/date.html'
property media
class next.forms.base.DateTimeField(*, input_formats=None, **kwargs)[source]
widget

alias of DateTimeInput

input_formats = <django.forms.fields.DateTimeFormatsIterator object>
default_error_messages = {'invalid': 'Enter a valid date/time.'}
prepare_value(value)[source]
to_python(value)[source]

Validate that the input can be converted to a datetime. Return a Python datetime.datetime object.

strptime(value, format)[source]
class next.forms.base.DateTimeInput(attrs=None, format=None)[source]
format_key = 'DATETIME_INPUT_FORMATS'
template_name = 'django/forms/widgets/datetime.html'
property media
class next.forms.base.DecimalField(*, max_value=None, min_value=None, max_digits=None, decimal_places=None, **kwargs)[source]
default_error_messages = {'invalid': 'Enter a number.'}
__init__(*, max_value=None, min_value=None, max_digits=None, decimal_places=None, **kwargs)[source]
to_python(value)[source]

Validate that the input is a decimal number. Return a Decimal instance or None for empty values. Ensure that there are no more than max_digits in the number and no more than decimal_places digits after the decimal point.

validate(value)[source]
widget_attrs(widget)[source]

Given a Widget instance (not a Widget class), return a dictionary of any HTML attributes that should be added to the Widget, based on this Field.

class next.forms.base.EmailField(**kwargs)[source]
widget

alias of EmailInput

default_validators = [<django.core.validators.EmailValidator object>]
__init__(**kwargs)[source]
class next.forms.base.EmailInput(attrs=None)[source]
input_type = 'email'
template_name = 'django/forms/widgets/email.html'
property media
class next.forms.base.FileField(*, max_length=None, allow_empty_file=False, **kwargs)[source]
widget

alias of ClearableFileInput

default_error_messages = {'contradiction': 'Please either submit a file or check the clear checkbox, not both.', 'empty': 'The submitted file is empty.', 'invalid': 'No file was submitted. Check the encoding type on the form.', 'max_length': '', 'missing': 'No file was submitted.'}
__init__(*, max_length=None, allow_empty_file=False, **kwargs)[source]
to_python(data)[source]
clean(data, initial=None)[source]

Validate the given value and return its “cleaned” value as an appropriate Python object. Raise ValidationError for any errors.

bound_data(_, initial)[source]

Return the value that should be shown for this field on render of a bound form, given the submitted POST data for the field and the initial data, if any.

For most fields, this will simply be data; FileFields need to handle it a bit differently.

has_changed(initial, data)[source]

Return True if data differs from initial.

class next.forms.base.FloatField(*, max_value=None, min_value=None, step_size=None, **kwargs)[source]
default_error_messages = {'invalid': 'Enter a number.'}
to_python(value)[source]

Validate that float() can be called on the input. Return the result of float() or None for empty values.

validate(value)[source]
widget_attrs(widget)[source]

Given a Widget instance (not a Widget class), return a dictionary of any HTML attributes that should be added to the Widget, based on this Field.

class next.forms.base.HiddenInput(attrs=None)[source]
input_type = 'hidden'
template_name = 'django/forms/widgets/hidden.html'
property media
class next.forms.base.ImageField(*, max_length=None, allow_empty_file=False, **kwargs)[source]
default_validators = [<function validate_image_file_extension>]
default_error_messages = {'invalid_image': 'Upload a valid image. The file you uploaded was either not an image or a corrupted image.'}
to_python(data)[source]

Check that the file-upload field data contains a valid image (GIF, JPG, PNG, etc. – whatever Pillow supports).

widget_attrs(widget)[source]

Given a Widget instance (not a Widget class), return a dictionary of any HTML attributes that should be added to the Widget, based on this Field.

class next.forms.base.IntegerField(*, max_value=None, min_value=None, step_size=None, **kwargs)[source]
widget

alias of NumberInput

default_error_messages = {'invalid': 'Enter a whole number.'}
re_decimal = <SimpleLazyObject: re.compile('\\.0*\\s*$')>
__init__(*, max_value=None, min_value=None, step_size=None, **kwargs)[source]
to_python(value)[source]

Validate that int() can be called on the input. Return the result of int() or None for empty values.

widget_attrs(widget)[source]

Given a Widget instance (not a Widget class), return a dictionary of any HTML attributes that should be added to the Widget, based on this Field.

class next.forms.base.MultipleChoiceField(*, choices=(), **kwargs)[source]
hidden_widget

alias of MultipleHiddenInput

widget

alias of SelectMultiple

default_error_messages = {'invalid_choice': 'Select a valid choice. %(value)s is not one of the available choices.', 'invalid_list': 'Enter a list of values.'}
to_python(value)[source]

Return a string.

validate(value)[source]

Validate that the input is a list or tuple.

has_changed(initial, data)[source]

Return True if data differs from initial.

class next.forms.base.NumberInput(attrs=None)[source]
input_type = 'number'
template_name = 'django/forms/widgets/number.html'
property media
class next.forms.base.PasswordInput(attrs=None, render_value=False)[source]
input_type = 'password'
template_name = 'django/forms/widgets/password.html'
__init__(attrs=None, render_value=False)[source]
get_context(name, value, attrs)[source]
property media
class next.forms.base.RegexField(regex, **kwargs)[source]
__init__(regex, **kwargs)[source]

regex can be either a string or a compiled regular expression object.

property regex
class next.forms.base.Select(attrs=None, choices=())[source]
input_type = 'select'
template_name = 'django/forms/widgets/select.html'
option_template_name = 'django/forms/widgets/select_option.html'
add_id_index = False
checked_attribute = {'selected': True}
option_inherits_attrs = False
get_context(name, value, attrs)[source]
use_required_attribute(initial)[source]

Don’t render ‘required’ if the first <option> has a value, as that’s invalid HTML.

property media
class next.forms.base.SelectMultiple(attrs=None, choices=())[source]
allow_multiple_selected = True
value_from_datadict(data, files, name)[source]

Given a dictionary of data and this widget’s name, return the value of this widget or None if it’s not provided.

value_omitted_from_data(data, files, name)[source]
property media
class next.forms.base.TextInput(attrs=None)[source]
input_type = 'text'
template_name = 'django/forms/widgets/text.html'
property media
class next.forms.base.Textarea(attrs=None)[source]
template_name = 'django/forms/widgets/textarea.html'
__init__(attrs=None)[source]
property media
class next.forms.base.TimeInput(attrs=None, format=None)[source]
format_key = 'TIME_INPUT_FORMATS'
template_name = 'django/forms/widgets/time.html'
property media
class next.forms.base.TypedChoiceField(*, coerce=<function TypedChoiceField.<lambda>>, empty_value='', **kwargs)[source]
__init__(*, coerce=<function TypedChoiceField.<lambda>>, empty_value='', **kwargs)[source]
clean(value)[source]

Validate the given value and return its “cleaned” value as an appropriate Python object. Raise ValidationError for any errors.

class next.forms.base.URLField(*, assume_scheme=None, **kwargs)[source]
widget

alias of URLInput

default_error_messages = {'invalid': 'Enter a valid URL.'}
default_validators = [<django.core.validators.URLValidator object>]
__init__(*, assume_scheme=None, **kwargs)[source]
to_python(value)[source]

Return a string.

class next.forms.base.URLInput(attrs=None)[source]
input_type = 'url'
template_name = 'django/forms/widgets/url.html'
property media
exception next.forms.base.ValidationError(message, code=None, params=None)[source]

An error while validating data.

__init__(message, code=None, params=None)[source]

The message argument can be a single error, a list of errors, or a dictionary that maps field names to lists of errors. What we define as an “error” can be either a simple string or an instance of ValidationError with its message attribute set, and what we define as list or dictionary can be an actual list or dict or an instance of ValidationError with its error_list or error_dict attribute set.

property message_dict
property messages
update_error_dict(error_dict)[source]
class next.forms.base.Widget(attrs=None)[source]
needs_multipart_form = False
is_localized = False
is_required = False
supports_microseconds = True
use_fieldset = False
__init__(attrs=None)[source]
property is_hidden
subwidgets(name, value, attrs=None)[source]
format_value(value)[source]

Return a value as it should appear when rendered in a template.

get_context(name, value, attrs)[source]
render(name, value, attrs=None, renderer=None)[source]

Render the widget as an HTML string.

build_attrs(base_attrs, extra_attrs=None)[source]

Build an attribute dictionary.

value_from_datadict(data, files, name)[source]

Given a dictionary of data and this widget’s name, return the value of this widget or None if it’s not provided.

value_omitted_from_data(data, files, name)[source]
id_for_label(id_)[source]

Return the HTML ID attribute of this Widget for use by a <label>, given the ID of the field. Return an empty string if no ID is available.

This hook is necessary because some widgets have multiple HTML elements and, thus, multiple IDs. In that case, this method should return an ID value that corresponds to the first ID in the widget’s tags.

use_required_attribute(initial)[source]
property media

Markers

Dependency injection markers and provider for form parameters.

class next.forms.markers.DForm[source]

Annotation for injecting a form instance by class.

Use as DForm[MyForm] or DForm[“MyForm”].

class next.forms.markers.FormProvider[source]

Inject a form instance matching the annotation or the parameter name form.

priority = 40
can_handle(param: Parameter, context: object) bool[source]

Return True when context carries a form compatible with param.

resolve(_param: Parameter, context: object) object[source]

Return the form instance from context.

Dispatch

FormActionDispatch and build_form_namespace_for_action are the public members of this module, in the Advanced tier described above. The underscore-prefixed helpers (_bind_form_for_post, _normalize_handler_response, and similar symbols) are internal hooks and stay off the autodoc surface below. Treat them as the Internal hooks tier described above.

Shared POST pipeline and helpers for form action dispatch.

class next.forms.dispatch.FormActionDispatch[source]

Shared POST pipeline and response shaping for backends.

static dispatch(backend: FormActionBackend, request: HttpRequest, action_name: str, meta: dict[str, Any]) HttpResponse[source]

Validate the form, run the handler, or re-render errors.

static form_response(backend: FormActionBackend, request: HttpRequest, action_name: str, form: django_forms.Form | None, template_fragment: str | None) HttpResponse[source]

Return full-page HTML for an invalid form submission.

static render_form_fragment(backend: FormActionBackend, request: HttpRequest, action_name: str, form: django_forms.Form | None, template_fragment: str | None, page_file_path: Path) str[source]

Delegate to render_form_page_with_errors for the given page file.

static ensure_http_response(response: HttpResponse | str | None, request: HttpRequest | None = None, action_name: str | None = None, backend: FormActionBackend | None = None) HttpResponse[source]

Coerce None, str, or HttpResponse into an HttpResponse.

next.forms.dispatch.build_form_namespace_for_action(action_name: str, request: HttpRequest) types.SimpleNamespace | None[source]

Build the SimpleNamespace(form=…) used by {% form %} when lazy.

Manager

FormActionManager aggregates backends and exposes URL patterns.

Backends are loaded lazily from NEXT_FRAMEWORK[“DEFAULT_FORM_ACTION_BACKENDS”] on first access. Unlike the components and static managers, this manager does not subscribe to settings_reloaded, because @action registers handlers imperatively at import time. Auto-rebuilding on every reload would drop those registrations and break test runs that rely on session-scoped eager_load_pages. Tests that swap form-action settings must call next.testing.reset_form_actions() explicitly to drop the cached backend list.

class next.forms.manager.FormActionManager(backends: list[FormActionBackend] | None = None)[source]

Holds one or more backends and yields their URL patterns.

__init__(backends: list[FormActionBackend] | None = None) None[source]

Initialise with explicit backends or defer loading to settings.

__repr__() str[source]

Return a debug representation showing the number of backends.

__iter__() Iterator[URLPattern][source]

Yield concatenated URL patterns from each backend.

register_action(name: str, handler: Callable[..., Any], *, options: FormActionOptions | None = None) None[source]

Forward registration to the first backend.

clear_registries() None[source]

Clear every backend that exposes a clear_registry method.

Intended for test isolation. Backends that do not implement clear_registry are skipped silently.

get_action_url(action_name: str) str[source]

Return the reverse URL from the first backend that knows action_name.

render_form_fragment(request: HttpRequest, action_name: str, form: django_forms.Form | None, template_fragment: str | None = None, *, page_file_path: Path | None = None) str[source]

Delegate rendering to the first backend.

property default_backend: FormActionBackend

Return the first configured backend.

Backends

Form action backend contract and registry-based default implementation.

class next.forms.backends.ActionMeta[source]

Per-action data stored in the registry backend.

handler: Callable[..., Any]
form_class: type[django_forms.Form] | Callable[..., type[django_forms.Form]] | None
uid: str
class next.forms.backends.FormActionBackend[source]

Storage and HTTP dispatch for @action handlers.

abstractmethod register_action(name: str, handler: Callable[..., Any], *, options: FormActionOptions | None = None) None[source]

Record an action from the decorator.

abstractmethod get_action_url(action_name: str) str[source]

Return the reverse URL for action_name.

abstractmethod generate_urls() list[URLPattern][source]

Return URLconf entries for this backend.

abstractmethod dispatch(request: HttpRequest, uid: str) HttpResponse[source]

Run the handler for uid.

get_meta(action_name: str) dict[str, Any] | None[source]

Return optional per-action metadata for subclasses.

render_form_fragment(request: HttpRequest, action_name: str, form: django_forms.Form | None, template_fragment: str | None = None, *, page_file_path: Path | None = None) str[source]

Return custom HTML for validation errors (override in subclasses).

class next.forms.backends.FormActionFactory[source]

Instantiates backends from merged DEFAULT_FORM_ACTION_BACKENDS entries.

classmethod create_backend(config: dict[str, Any]) FormActionBackend[source]

Return a single backend instance for one settings entry.

The BACKEND key must be present and resolve to a FormActionBackend subclass. The next.E044 system check guarantees the key is present and importable. The next.E045 system check guarantees the imported class subclasses FormActionBackend. Both run before the factory does in production.

class next.forms.backends.FormActionOptions(form_class: type[django_forms.Form] | Callable[..., type[django_forms.Form]] | None = None, namespace: str | None = None)[source]

Options passed to register_action (used by the @action decorator).

form_class may be a Form subclass or a zero-or-more-argument callable that returns one. Callables are resolved per request at dispatch time, enabling factories like ModelAdmin.get_form().

form_class: type[django_forms.Form] | Callable[..., type[django_forms.Form]] | None = None
namespace: str | None = None
__init__(form_class: type[django_forms.Form] | Callable[..., type[django_forms.Form]] | None = None, namespace: str | None = None) None
class next.forms.backends.RegistryFormActionBackend(config: dict[str, Any] | None = None)[source]

In-memory actions behind one dispatcher path keyed by UID.

__init__(config: dict[str, Any] | None = None) None[source]

Create an empty action map. config is accepted for factory parity.

clear_registry() None[source]

Drop every registered action and reset the UID index.

Intended for test isolation. Use this to clear actions between independent test sessions that register overlapping names.

register_action(name: str, handler: Callable[..., Any], *, options: FormActionOptions | None = None) None[source]

Store handler, optional form class, and stable uid for the action name.

get_action_url(action_name: str) str[source]

Return the reverse URL for a registered action name.

generate_urls() list[URLPattern][source]

Return one catch-all route when at least one action is registered.

dispatch(request: HttpRequest, uid: str) HttpResponse[source]

Forward a POST request to FormActionDispatch.dispatch.

get_meta(action_name: str) dict[str, Any] | None[source]

Return stored ActionMeta for the name, if any.

render_form_fragment(request: HttpRequest, action_name: str, form: django_forms.Form | None, template_fragment: str | None = None, *, page_file_path: Path | None = None) str[source]

Render validation-error HTML for a page module path.

Action URL Helpers

Stable UIDs and related helpers for @action endpoints.

next.forms.uid.redirect_to_origin(request: HttpRequest, fallback: str = '/') HttpResponseRedirect[source]

Redirect back to the page that rendered the form.

next.forms.uid.validated_next_form_page_path(request: HttpRequest) Path | None[source]

Return a trusted page.py path from POST _next_form_page, or None.

Accepts both real page.py files and virtual ones — directories whose only source is a sibling template.djx (the file router already emits routes for those; see FilesystemTreeDispatcher._visit). The downstream renderer (_load_python_module_memo, _load_static_body) tolerates a missing module and falls back to the template, so virtual pages survive the re-render path on form-validation failures.

Formset Helpers

Helpers for working with Django formsets in custom UIs.

next.forms.formsets.cleanup_extra_initial(formset: BaseFormSet) None[source]

Drop initial values on blank extra rows so untouched rows skip validation.

Idempotent. Targets rows with empty_permitted=True and no instance pk.

Frozen Specs

Frozen-dataclass specs for rendering Django forms in custom templates.

class next.forms.serializers.FieldSpec(bound: BoundField, kind: FieldKind, input_type: str, value: Any, selected: tuple[str, ...], is_extra: bool)[source]

Render-time descriptor for one BoundField.

bound: BoundField
kind: FieldKind
input_type: str
value: Any
selected: tuple[str, ...]
is_extra: bool
__init__(bound: BoundField, kind: FieldKind, input_type: str, value: Any, selected: tuple[str, ...], is_extra: bool) None
class next.forms.serializers.FormSectionSpec(label: str, description: str, fields: tuple[FieldSpec, ...])[source]

One labelled section in a FormSpec (matches a Django admin fieldset).

label: str
description: str
fields: tuple[FieldSpec, ...]
__init__(label: str, description: str, fields: tuple[FieldSpec, ...]) None
class next.forms.serializers.FormSpec(sections: tuple[FormSectionSpec, ...], non_field_errors: tuple[str, ...])[source]

Top-level spec for rendering a form with optional fieldsets.

sections: tuple[FormSectionSpec, ...]
non_field_errors: tuple[str, ...]
__init__(sections: tuple[FormSectionSpec, ...], non_field_errors: tuple[str, ...]) None
class next.forms.serializers.FormsetRowSpec(fields: tuple[FieldSpec, ...], hidden_html: str, delete_field: BoundField | None, errors: Mapping[str, list[str]], is_extra: bool)[source]

One row inside a FormsetSpec. Render hidden_html with |safe.

fields: tuple[FieldSpec, ...]
hidden_html: str
delete_field: BoundField | None
errors: Mapping[str, list[str]]
is_extra: bool
__init__(fields: tuple[FieldSpec, ...], hidden_html: str, delete_field: BoundField | None, errors: Mapping[str, list[str]], is_extra: bool) None
class next.forms.serializers.FormsetSpec(prefix: str, verbose_name_plural: str, management_form: BaseForm, rows: tuple[FormsetRowSpec, ...], non_form_errors: tuple[str, ...], can_delete: bool)[source]

Template-friendly view of a Django formset (inline or standalone).

prefix: str
verbose_name_plural: str
management_form: BaseForm
rows: tuple[FormsetRowSpec, ...]
non_form_errors: tuple[str, ...]
can_delete: bool
__init__(prefix: str, verbose_name_plural: str, management_form: BaseForm, rows: tuple[FormsetRowSpec, ...], non_form_errors: tuple[str, ...], can_delete: bool) None
next.forms.serializers.field_spec(bound: BoundField, *, is_extra: bool = False) FieldSpec[source]

Classify a BoundField into a FieldSpec.

next.forms.serializers.form_spec(form: BaseForm, fieldsets: Sequence[tuple[str | None, Mapping[str, Any]]] | None = None) FormSpec[source]

Group form’s fields into sections per Django admin (label, opts).

next.forms.serializers.formset_spec(formset: BaseFormSet) FormsetSpec[source]

Build a FormsetSpec from a Django formset.

Signals

See Signals Reference and Form Signals for the form signals (action_registered, action_dispatched, form_validation_failed).

See Also

See also

Forms for the topic subtree. Extending for plugging custom backends. Testing for helpers used when asserting handlers. Action Dispatch for the dispatch pipeline.