Skip to content

fix(query): Preserve metadata on inherited Model Query fields#58

Merged
mvaled merged 1 commit into
masterfrom
fix-query-annotations-with-mro
May 28, 2026
Merged

fix(query): Preserve metadata on inherited Model Query fields#58
mvaled merged 1 commit into
masterfrom
fix-query-annotations-with-mro

Conversation

@mvaled
Copy link
Copy Markdown
Collaborator

@mvaled mvaled commented May 28, 2026

QueryPatcher.for_component used to look up the rewritten annotation in component.__annotations__[field_name] and fall back to field.annotation otherwise. Both cls.__annotations__ and that fallback drop the PlainSerializer / PlainValidator that annotate_model attaches for Django Model and QuerySet types — __annotations__ because it is the class's own dict (no MRO walk), and field.annotation because pydantic stores the bare type with metadata kept separately.

The result was that a public component which inherited a Query field like

editing: Annotated[Item | None, Query("editing"), Field(default=None)]

from an abstract base would build an adapter that knew how to validate but not how to serialise: as soon as the URL needed to be updated for the chosen instance, dump_python raised
PydanticSerializationError: Unable to serialize unknown type.

Reconstruct the annotation from field.annotation + field.metadata instead. Pydantic carries the metadata along through inheritance, so the adapter now picks up the model-PK serializer regardless of where the field was declared in the MRO.

Add test_query.py covering both inherited and own-field declaration so the regression cannot return.

`QueryPatcher.for_component` used to look up the rewritten annotation in
`component.__annotations__[field_name]` and fall back to `field.annotation`
otherwise.  Both `cls.__annotations__` and that fallback drop the
`PlainSerializer` / `PlainValidator` that `annotate_model` attaches for
Django Model and QuerySet types — `__annotations__` because it is the
class's *own* dict (no MRO walk), and `field.annotation` because pydantic
stores the bare type with metadata kept separately.

The result was that a public component which inherited a Query field like

    editing: Annotated[Item | None, Query("editing"), Field(default=None)]

from an abstract base would build an adapter that knew how to validate but
not how to serialise: as soon as the URL needed to be updated for the
chosen instance, `dump_python` raised
`PydanticSerializationError: Unable to serialize unknown type`.

Reconstruct the annotation from `field.annotation` + `field.metadata`
instead.  Pydantic carries the metadata along through inheritance, so the
adapter now picks up the model-PK serializer regardless of where the
field was declared in the MRO.

Add `test_query.py` covering both inherited and own-field declaration so
the regression cannot return.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@mvaled mvaled merged commit fcd2451 into master May 28, 2026
3 checks passed
@mvaled mvaled deleted the fix-query-annotations-with-mro branch May 28, 2026 11:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant