Skip to content

Commit 3c3abd7

Browse files
committed
Add field_title_generator param to Field, add tests
1 parent 194bc41 commit 3c3abd7

File tree

2 files changed

+46
-1
lines changed

2 files changed

+46
-1
lines changed

sqlmodel/main.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ def Field(
212212
validation_alias: Optional[str] = None,
213213
serialization_alias: Optional[str] = None,
214214
title: Optional[str] = None,
215+
field_title_generator: Optional[Callable[[str, PydanticFieldInfo], str]] = None,
215216
description: Optional[str] = None,
216217
examples: Optional[list[Any]] = None,
217218
deprecated: Union[Deprecated, str, bool, None] = None,
@@ -259,6 +260,7 @@ def Field(
259260
validation_alias: Optional[str] = None,
260261
serialization_alias: Optional[str] = None,
261262
title: Optional[str] = None,
263+
field_title_generator: Optional[Callable[[str, PydanticFieldInfo], str]] = None,
262264
description: Optional[str] = None,
263265
examples: Optional[list[Any]] = None,
264266
deprecated: Union[Deprecated, str, bool, None] = None,
@@ -315,6 +317,7 @@ def Field(
315317
validation_alias: Optional[str] = None,
316318
serialization_alias: Optional[str] = None,
317319
title: Optional[str] = None,
320+
field_title_generator: Optional[Callable[[str, PydanticFieldInfo], str]] = None,
318321
description: Optional[str] = None,
319322
examples: Optional[list[Any]] = None,
320323
deprecated: Union[Deprecated, str, bool, None] = None,
@@ -352,6 +355,7 @@ def Field(
352355
validation_alias: Optional[str] = None,
353356
serialization_alias: Optional[str] = None,
354357
title: Optional[str] = None,
358+
field_title_generator: Optional[Callable[[str, PydanticFieldInfo], str]] = None,
355359
description: Optional[str] = None,
356360
examples: Optional[list[Any]] = None,
357361
deprecated: Union[Deprecated, str, bool, None] = None,
@@ -390,7 +394,13 @@ def Field(
390394
) -> Any:
391395
current_schema_extra = schema_extra or {}
392396

393-
for param_name in ("strict", "examples", "deprecated", "exclude_if"):
397+
for param_name in (
398+
"strict",
399+
"examples",
400+
"deprecated",
401+
"exclude_if",
402+
"field_title_generator",
403+
):
394404
if param_name in current_schema_extra:
395405
msg = f"Pass `{param_name}` parameter directly to Field instead of passing it via `schema_extra`"
396406
warnings.warn(msg, DeprecationWarning, stacklevel=2)
@@ -402,6 +412,9 @@ def Field(
402412
current_examples = examples or current_schema_extra.pop("examples", None)
403413
current_deprecated = deprecated or current_schema_extra.pop("deprecated", None)
404414
current_exclude_if = exclude_if or current_schema_extra.pop("exclude_if", None)
415+
current_field_title_generator = field_title_generator or current_schema_extra.pop(
416+
"field_title_generator", None
417+
)
405418
field_info_kwargs = {
406419
"alias": alias,
407420
"title": title,
@@ -411,6 +424,7 @@ def Field(
411424
"exclude": exclude,
412425
"exclude_if": current_exclude_if,
413426
"include": include,
427+
"field_title_generator": current_field_title_generator,
414428
"const": const,
415429
"gt": gt,
416430
"ge": ge,

tests/test_pydantic/test_field.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,3 +193,34 @@ class Model(SQLModel):
193193
assert dict1["name"] == "Alice"
194194

195195
assert "name" not in dict2
196+
197+
198+
def test_field_title_generator():
199+
def upper(value: str, _: Any) -> str:
200+
return value.upper()
201+
202+
class Model(SQLModel):
203+
name: str = Field(field_title_generator=upper)
204+
age: int
205+
206+
model_schema = Model.model_json_schema()
207+
assert model_schema["properties"]["name"]["title"] == "NAME"
208+
assert model_schema["properties"]["age"]["title"] == "Age"
209+
210+
211+
def test_field_title_generator_via_schema_extra():
212+
def upper(value: str, _: Any) -> str:
213+
return value.upper()
214+
215+
with pytest.warns(
216+
DeprecationWarning,
217+
match="Pass `field_title_generator` parameter directly to Field instead of passing it via `schema_extra`",
218+
):
219+
220+
class Model(SQLModel):
221+
name: str = Field(schema_extra={"field_title_generator": upper})
222+
age: int
223+
224+
model_schema = Model.model_json_schema()
225+
assert model_schema["properties"]["name"]["title"] == "NAME"
226+
assert model_schema["properties"]["age"]["title"] == "Age"

0 commit comments

Comments
 (0)