Skip to content
11 changes: 10 additions & 1 deletion sqlmodel/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ def Field(
max_length: Optional[int] = None,
allow_mutation: bool = True,
regex: Optional[str] = None,
pattern: Optional[str] = None,
discriminator: Optional[str] = None,
repr: bool = True,
primary_key: Union[bool, UndefinedType] = Undefined,
Expand Down Expand Up @@ -285,6 +286,7 @@ def Field(
max_length: Optional[int] = None,
allow_mutation: bool = True,
regex: Optional[str] = None,
pattern: Optional[str] = None,
discriminator: Optional[str] = None,
repr: bool = True,
primary_key: Union[bool, UndefinedType] = Undefined,
Expand Down Expand Up @@ -339,6 +341,7 @@ def Field(
max_length: Optional[int] = None,
allow_mutation: bool = True,
regex: Optional[str] = None,
pattern: Optional[str] = None,
discriminator: Optional[str] = None,
repr: bool = True,
sa_column: Union[Column, UndefinedType] = Undefined, # type: ignore
Expand Down Expand Up @@ -374,6 +377,7 @@ def Field(
max_length: Optional[int] = None,
allow_mutation: bool = True,
regex: Optional[str] = None,
pattern: Optional[str] = None,
discriminator: Optional[str] = None,
repr: bool = True,
primary_key: Union[bool, UndefinedType] = Undefined,
Expand All @@ -389,6 +393,12 @@ def Field(
schema_extra: Optional[Dict[str, Any]] = None,
) -> Any:
current_schema_extra = schema_extra or {}

if IS_PYDANTIC_V2:
current_schema_extra.update(pattern=pattern or regex)
else:
current_schema_extra.update(regex=regex or pattern)
Copy link
Member

@YuriiMotov YuriiMotov Oct 7, 2025

Choose a reason for hiding this comment

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

I still think we should deprecate regex parameter and prioritize pattern regardless the version of Pydantic installed.
Let's leave this decision to Sebastian

Copy link
Author

Choose a reason for hiding this comment

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

I would leave it like this, separate but not deprecate any, it is the main purpose of this PR, to support both and after migrating from pydantic v1 to v2 it remains compatible

Copy link
Member

Choose a reason for hiding this comment

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

It's just a bit confusing that we will have 2 duplicating parameters.
Pydantic has marked regex as deprecated in V2

Copy link
Author

Choose a reason for hiding this comment

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

Yes, that's true, but since sqlmodel supports both versions we should keep compatibility.
Otherwise this PR would be just renaming the parameter

Copy link
Member

@YuriiMotov YuriiMotov Oct 7, 2025

Choose a reason for hiding this comment

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

We support both, but mark old one as deprecated. This way we give users time to update their code bases to use new parameter instead of old one.
Later we will drop regex and only allow pattern regardless the Pydantic version.
I think we should go this way

Copy link
Author

Choose a reason for hiding this comment

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

Ok. Then:

  1. Support both parameters (like it is)
  2. In future versions schema_extra and regex will be removed in order to support just pattern as pydantic have done

Copy link
Member

@YuriiMotov YuriiMotov Oct 7, 2025

Choose a reason for hiding this comment

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

Yes, but schema_extra will be just renamed to json_schema_extra and schema_extra will be marked as deprecated


field_info = FieldInfo(
default,
default_factory=default_factory,
Expand All @@ -411,7 +421,6 @@ def Field(
min_length=min_length,
max_length=max_length,
allow_mutation=allow_mutation,
regex=regex,
discriminator=discriminator,
repr=repr,
primary_key=primary_key,
Expand Down
14 changes: 14 additions & 0 deletions tests/test_pydantic/test_field.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,17 @@ class Model(SQLModel):

instance = Model(id=123, foo="bar")
assert "foo=" not in repr(instance)


@pytest.mark.parametrize("param", ["regex", "pattern"])
def test_field_regex_param(param: str):
class DateModel(SQLModel):
date_1: str = Field(**{param: r"^\d{2}-\d{2}-\d{4}$"})
date_2: str = Field(schema_extra={param: r"^\d{2}-\d{2}-\d{4}$"})

DateModel(date_1="12-31-2024", date_2="12-31-2024")
# Validates correctly

with pytest.raises(ValidationError):
DateModel(date_1="2024-12-31", date_2="2024-12-31")
# This should raise a ValueError due to regex mismatch