Validation¶
Every generated scalar is a real Django field, cleaned through Django's normal
pipeline. The composite field then reconstructs the complete JSON document and
validates it independently with jsonschema's Draft 2020-12 validator. Finally,
application validators run. Custom fields cannot bypass document constraints.
Errors include JSON Pointer locations (/levels/0/points), appear in the widget
summary and attach to the nearest editable child. Array locations account for
deleted rows. Invalid schemas/unresolved references raise ImproperlyConfigured
instead of being silently ignored. max_errors=100 bounds collected errors.
Resources and formats¶
configuration = JSONSchemaFormField(
schema={"$ref": "urn:example:configuration"},
schema_resources={
"urn:example:configuration": {
"type": "object",
"properties": {"contact": {"type": "string", "format": "email"}},
"required": ["contact"],
"additionalProperties": False,
},
},
validate_formats=True,
)
Alternatively pass schema_registry=referencing.Registry(...) for explicitly
controlled resource retrieval. The default registry does not access the network.
format_checker accepts a jsonschema.FormatChecker, including custom checks.
Document format checks default to off; built-in Django format fields retain
their own validation. Content keywords do not decode files automatically.
For validation outside a form:
from django_native_jsonform import JSONSchemaValidator
validator = JSONSchemaValidator(SCHEMA, validate_formats=True)
validator(value) # Raises JSONFormValidationError on an invalid document.
issues = validator.issues(value) # SchemaIssue path, pointer, keyword, message.
normalize_schema translates legacy choices, boolean leaf required and
readonly without mutating the original schema or data in const/default.
Whole-value validators¶
Pass Django validators to JSONSchemaFormField as usual:
def validate_configuration(value):
if value.get("starts_on") and value.get("ends_on"):
if value["starts_on"] > value["ends_on"]:
raise ValidationError("The date range is invalid.")
configuration = JSONSchemaFormField(
schema=SCHEMA,
validators=[validate_configuration],
)
Errors attached to a child path¶
Use JSONFormValidationError to put errors next to generated fields:
from django_native_jsonform import JSONFormValidationError
def validate_configuration(value):
errors = {}
if value.get("path", "").endswith("/"):
errors["path"] = "Path must not end with /."
for index, level in enumerate(value.get("levels", [])):
if level.get("points", 0) < 0:
errors[f"levels.{index}.points"] = "Points cannot be negative."
if errors:
raise JSONFormValidationError(
"Invalid configuration",
errors=errors,
)
Paths accept legacy dot notation or JSON Pointer (/levels/0/points). Use
JSON Pointer for property names containing dots or slashes. Array indices refer
to the reconstructed document, after deleted rows are removed. Errors attach to
the nearest active editable node and remain available in the widget summary.
Custom Django fields¶
A registered field or an override may implement any normal Django validation:
validators, to_python, validate, and run_validators. Its cleaned value is
serialized into JSON through the built-in serializer or a path-specific
serialize callable.
The built-in serializer handles Django models/querysets, Decimal, date/time
objects, and UUIDs.