Skip to content

🐛 Forward by_alias and by_name to model_validate#1977

Open
ATOM00blue wants to merge 1 commit into
fastapi:mainfrom
ATOM00blue:fix-model-validate-by-alias-by-name
Open

🐛 Forward by_alias and by_name to model_validate#1977
ATOM00blue wants to merge 1 commit into
fastapi:mainfrom
ATOM00blue:fix-model-validate-by-alias-by-name

Conversation

@ATOM00blue
Copy link
Copy Markdown

Description

SQLModel overrides model_validate, but the override does not accept or forward the by_alias and by_name arguments that Pydantic's model_validate supports.

SQLModel requires pydantic>=2.11, and both by_alias and by_name have been part of model_validate since Pydantic 2.11, so they are always available. Despite that, calling them on a SQLModel fails:

from sqlmodel import SQLModel, Field

class Hero(SQLModel):
    name: str = Field(alias="heroName")

Hero.model_validate({"heroName": "Deadpond"}, by_alias=True)
# TypeError: SQLModel.model_validate() got an unexpected keyword argument 'by_alias'

Hero.model_validate({"name": "Deadpond"}, by_name=True)
# TypeError: SQLModel.model_validate() got an unexpected keyword argument 'by_name'

The plain Pydantic equivalent works, so this is a gap in SQLModel's override. It forces users with aliased fields to drop down to __pydantic_validator__ or restructure their input.

This is also reported in #1824.

Fix

Add by_alias and by_name to the model_validate override and to the internal sqlmodel_validate helper, forwarding them to validate_python. This mirrors how the other validation arguments (strict, from_attributes, context) are already handled, and keeps model_validate consistent with Pydantic.

No version gating is needed since the supported Pydantic floor (2.11) already includes both parameters.

Tests

Added parametrized tests in tests/test_aliases.py that run the same assertions against a plain Pydantic model and the equivalent SQLModel, covering by_name=True and the by_alias=True, by_name=True combination. They fail on main with the TypeError above and pass with this change.

SQLModel overrides model_validate but did not pass through the by_alias
and by_name arguments that Pydantic supports. Since SQLModel requires
pydantic>=2.11, where both are always available, calling
Model.model_validate(data, by_alias=True) (or by_name=True) raised
TypeError: unexpected keyword argument.

Add both parameters to the model_validate override and to
sqlmodel_validate, forwarding them to validate_python.
Copilot AI review requested due to automatic review settings May 22, 2026 02:30
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds support in SQLModel for Pydantic-style input population controls when validating models, enabling callers to explicitly choose whether aliases and/or field names are accepted during model_validate.

Changes:

  • Extended SQLModel.model_validate(...) to accept by_alias and by_name keyword arguments and forward them to the underlying validator.
  • Extended the internal sqlmodel_validate(...) compatibility layer to pass by_alias/by_name through to __pydantic_validator__.validate_python(...).
  • Added tests covering default behavior vs by_name=True, and combined by_alias=True, by_name=True.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
tests/test_aliases.py Adds regression tests for model_validate behavior with by_name and combined by_alias/by_name.
sqlmodel/main.py Exposes by_alias and by_name on the public SQLModel.model_validate API and forwards them.
sqlmodel/_compat.py Threads by_alias/by_name through sqlmodel_validate into Pydantic’s validator call.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

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.

3 participants