ENGINEERING NOTE / VALIDATION

The model save boundary.

Reuse validation rules while keeping persistence responsibilities explicit.

The problem

Applications can repeat the same data rules in request handling, serializers, and model-level code. These copies can drift, creating different acceptance rules for the same data.

The decision

Connect a Pydantic schema to a Nova model through NovaConfig. The model's save implementation invokes the validation lifecycle before delegating persistence to Django. A shared schema provides a reusable data contract at that integration point.

Responsibilities

LayerResponsibility
PydanticValidate data against configured schema rules.
NovaConnect validation and serialization to supported Django integration points.
Django ORMModel lifecycle, query behavior, and database persistence.
DatabaseEnforce constraints for writes, including writers outside the application.

Alternatives and trade-offs

Validation only at the API boundary is straightforward for a single entry point, but does not cover application code that writes directly through models. A model save hook covers that path, while adding runtime work to each validated save.

Database constraints remain the appropriate protection for database invariants. Pydantic schemas complement those constraints and cannot replace them.

Where this boundary stops

Bulk operations, raw SQL, and external writers may bypass model save hooks. They require their own validation strategy and database constraints. Static type checking also cannot establish that incoming runtime data is valid.

How to evaluate it

  1. Run the Quick Start with a pinned library release.
  2. Check a successful save and an invalid input case.
  3. Test the write paths your application actually uses, including bulk updates and transactions.
  4. Inspect the model implementation and validation lifecycle before extending the integration.

This note describes the integration pattern. The selected library release and its tests are the authority for exact API behavior.