diff --git a/fastapi/_compat/__init__.py b/fastapi/_compat/__init__.py index 5d772e583..b2ae5adc7 100644 --- a/fastapi/_compat/__init__.py +++ b/fastapi/_compat/__init__.py @@ -33,6 +33,7 @@ from .main import ( from .model_field import ModelField as ModelField from .shared import PYDANTIC_V2 as PYDANTIC_V2 from .shared import PYDANTIC_VERSION_MINOR_TUPLE as PYDANTIC_VERSION_MINOR_TUPLE +from .shared import annotation_is_pydantic_v1 as annotation_is_pydantic_v1 from .shared import field_annotation_is_scalar as field_annotation_is_scalar from .shared import ( is_uploadfile_or_nonable_uploadfile_annotation as is_uploadfile_or_nonable_uploadfile_annotation, diff --git a/fastapi/_compat/main.py b/fastapi/_compat/main.py index 6cc10dd38..f45f8d33d 100644 --- a/fastapi/_compat/main.py +++ b/fastapi/_compat/main.py @@ -205,8 +205,9 @@ def _model_rebuild(model: Type[BaseModel]) -> None: def get_compat_model_name_map(fields: List[ModelField]) -> ModelNameMap: - if fields and isinstance(fields[0], v1.ModelField): - models = v1.get_flat_models_from_fields(fields, known_models=set()) + v1_models = [field for field in fields if isinstance(field, v1.ModelField)] + if v1_models: + models = v1.get_flat_models_from_fields(v1_models, known_models=set()) return v1.get_model_name_map(models) # type: ignore[no-any-return] return {} diff --git a/fastapi/utils.py b/fastapi/utils.py index 18c2a4b97..4c74d8d9d 100644 --- a/fastapi/utils.py +++ b/fastapi/utils.py @@ -23,11 +23,12 @@ from fastapi._compat import ( Undefined, UndefinedType, Validator, + annotation_is_pydantic_v1, lenient_issubclass, v1, ) from fastapi.datastructures import DefaultPlaceholder, DefaultType -from pydantic import BaseModel, create_model +from pydantic import BaseModel from pydantic.fields import FieldInfo from typing_extensions import Literal @@ -86,7 +87,7 @@ def create_model_field( ) -> ModelField: class_validators = class_validators or {} - if lenient_issubclass(type_, v1.BaseModel) or version == "1": + if annotation_is_pydantic_v1(type_) or version == "1": model_config = v1.BaseConfig field_info = field_info or v1.FieldInfo() kwargs = { @@ -124,6 +125,7 @@ def create_cloned_field( ) -> ModelField: if PYDANTIC_V2: from ._compat import v2 + if isinstance(field, v2.ModelField): # type: ignore[name-defined] return field # cloned_types caches already cloned types to support recursive models and improve @@ -143,7 +145,8 @@ def create_cloned_field( cloned_types[original_type] = use_type for f in original_type.__fields__.values(): use_type.__fields__[f.name] = create_cloned_field( - f, cloned_types=cloned_types, + f, + cloned_types=cloned_types, ) new_field = create_model_field(name=field.name, type_=use_type, version="1") new_field.has_alias = field.has_alias # type: ignore[attr-defined]