Skip to content

1.16.0 — construction semantics

Choose a tag to compare

@vsdudakov vsdudakov released this 31 Aug 05:14
· 8 commits to main since this release
504a7da

Construction semantics release: an instance now agrees with the row it writes in four places that previously needed application-side shims, plus a bulk_update batching fix. Highlights:

Added

  • Model.__iter__: instances iterate as (name, value) pairs, so dict(instance) works and pair-walking consumers (pydantic from_attributes, serializers, factories) take a model directly. Declared columns first in declaration order, columns absent under only()/defer() skipped rather than fetched, private attributes omitted, Meta.extra_kwargs = "store" extras last.

Changed

  • An explicit <name>_id wins over a relation object at construction. Book(author=obj, author_id=x) used to store obj.pk; it now keeps x (by field name or db-column alias), and an object whose pk disagrees is not cached as the prefetched relation. Factories need this: a SubFactory is evaluated even when the caller passes author_id=. Passing only one form is unchanged.
  • auto_now_add fills the column instead of imposing a value. Backdated fixtures, imports and backfills keep the stamp they pass. auto_now still always stamps, as does a field declaring both.

Fixed

  • Foreign-key columns are coerced on assignment. create(parent_id=str(pk)) left the raw str on the instance, so child.parent_id == parent.id was False until re-fetch. ForeignKeyFieldInstance.to_python_value now mirrors to_db and the <name>_id column is normalised in __init__ like every other coerced column.
  • bulk_update respects the dialect's bind-parameter ceiling. Batches are clamped from max_bind_params (each row costs a (pk, value) pair per field plus a pk slot in WHERE ... IN), so a large batch_size no longer overflows PostgreSQL's 65535 / SQL Server's 2100 limit; SQLite now declares its default 32766.

Full details in CHANGELOG.md.