Add a blueprint for pydantic 2#1028
Conversation
| ) | ||
| auto_schema.registry.register_on_missing(component) | ||
|
|
||
| return schema |
There was a problem hiding this comment.
ℹ️ Here's the difference between the two blueprints for pydantic.
The change is to use model_json_schema() instead of model_schema(), which takes a ref_template argument instead of ref_prefix.
Note, I didn't see in the pydantic migration notes anything about migrating from the old model_schema().
$ diff -U5 docs/blueprints/pydantic.py docs/blueprints/pydantic2.py
--- docs/blueprints/pydantic.py 2023-07-17 13:38:19.059201949 +0200
+++ docs/blueprints/pydantic2.py 2023-07-17 13:41:14.883652117 +0200
@@ -1,9 +1,9 @@
from drf_spectacular.extensions import OpenApiSerializerExtension
from drf_spectacular.plumbing import ResolvedComponent
-from pydantic.schema import model_schema
+from pydantic.json_schema import model_json_schema
class PydanticExtension(OpenApiSerializerExtension):
target_class = "pydantic.BaseModel"
match_subclasses = True
@@ -12,11 +12,11 @@
return self.target.__name__
def map_serializer(self, auto_schema, direction):
# let pydantic generate a JSON schema
- schema = model_schema(self.target, ref_prefix="#/components/schemas/")
+ schema = model_json_schema(self.target, ref_template="#/components/schemas")
# pull out potential sub-schemas and put them into component section
for sub_name, sub_schema in schema.pop("definitions", {}).items():
component = ResolvedComponent(
name=sub_name,
Codecov ReportPatch and project coverage have no change.
Additional details and impacted files@@ Coverage Diff @@
## master #1028 +/- ##
=======================================
Coverage 98.55% 98.55%
=======================================
Files 68 68
Lines 8367 8367
=======================================
Hits 8246 8246
Misses 121 121 ☔ View full report in Codecov by Sentry. |
|
awesome! thx @caarmen |
|
Actually, it seems there's an issue, sorry I didn't catch it earlier :/ For a model with a field which is a list of another pydantic model, the field isn't being generated correctly. Looks the pydantic 1 I'll update here if/when I find more information. |
|
yes, I also noticed the 2 versions are subtly different. Stuff wasn't just renamed. Feel free to do another PR. |
|
I hit an issue trying to work around this. I opened an issue on Pydantic: pydantic/pydantic#6741 I haven't managed to generate an openapi json with either Looks like pydantic has an api to be able to put definitions in Maybe (hopefully) I just didn't understand the pydantic api enough. 🤞🏻 |
|
I've figured out a workaround, but it's not very clean :/ It basically takes the Tested in my project: +import json
+
from drf_spectacular.extensions import OpenApiSerializerExtension
from drf_spectacular.plumbing import ResolvedComponent
from pydantic.json_schema import model_json_schema
class PydanticExtension(OpenApiSerializerExtension):
target_class = "pydantic.BaseModel"
match_subclasses = True
def get_name(self, auto_schema, direction):
return self.target.__name__
def map_serializer(self, auto_schema, direction):
# let pydantic generate a JSON schema
- schema = model_json_schema(self.target, ref_template="#/components/schemas")
+ schema = model_json_schema(self.target)
# pull out potential sub-schemas and put them into component section
- for sub_name, sub_schema in schema.pop("definitions", {}).items():
+ for sub_name, sub_schema in schema.pop("$defs", {}).items():
component = ResolvedComponent(
name=sub_name,
type=ResolvedComponent.SCHEMA,
object=sub_name,
schema=sub_schema,
)
auto_schema.registry.register_on_missing(component)
- return schema
+ # Workaround to force placing definitions in components/schemas.
+ # Pydantic places definitions in $defs, and we want them in components/schemas,
+ # but using ref_template="#/components/schemas in model_json_schema() makes us lose sub objects.
+ # See https://github.com/pydantic/pydantic/issues/6741
+ schema_with_relocated_defs = json.loads(json.dumps(schema).replace("#/$defs/", "#/components/schemas/"))
+ return schema_with_relocated_defs
If you want, I can open a PR for this. But I understand it's not very clean! 😄 We can wait for some news on the pydantic issue instead. |
|
scratch that, I can do a proper fix I think 😁 |
|
Here's a PR: My confidence in this isn't at 100% for now, we could say 😅 . So do feel free to try it out a bit before merging. I didn't find unit tests for blueprints in the project. |
Add a blueprint to support pydantic models, using the pydantic 2.x version.
Here's the pydantic 2 migration guide: https://docs.pydantic.dev/latest/migration/