diff --git a/django2pydantic/__init__.py b/django2pydantic/__init__.py index e8bd7b4..12b688b 100644 --- a/django2pydantic/__init__.py +++ b/django2pydantic/__init__.py @@ -1,7 +1,7 @@ """Super schema packages.""" -from django2pydantic.schema import django2pydantic +from django2pydantic.schema import Schema from django2pydantic.types import Infer, InferExcept, MetaFields, ModelFields -__all__ = ["Infer", "InferExcept", "ModelFields", "MetaFields", "django2pydantic"] +__all__ = ["Infer", "InferExcept", "ModelFields", "MetaFields", "Schema"] __version__ = "0.0.1" diff --git a/django2pydantic/base.py b/django2pydantic/base.py index d1e8fed..ba140bd 100644 --- a/django2pydantic/base.py +++ b/django2pydantic/base.py @@ -261,8 +261,8 @@ def __new__( # pylint: disable=W0222,C0204 namespace: Namespace, **kwargs: Kwargs, ) -> type[BaseModel]: - """Create a new django2pydantic class.""" - if name == "django2pydantic": + """Create a new Schema class.""" + if name == "Schema": # TODO: detect more reliably if this is the base class return super().__new__(cls, name, bases, namespace, **kwargs) if "Meta" not in namespace: @@ -270,7 +270,7 @@ def __new__( # pylint: disable=W0222,C0204 raise ValueError(msg) if getattr(namespace["Meta"], "model", None) is None: - msg = f"model class is required in Meta class for {name}" + msg = f"'model' attribute is required in Meta class for {name}" raise ValueError(msg) model_class = namespace["Meta"].model diff --git a/django2pydantic/getter.py b/django2pydantic/getter.py index 4e38422..b5b3aed 100644 --- a/django2pydantic/getter.py +++ b/django2pydantic/getter.py @@ -1,6 +1,6 @@ """Getter for Pydantic related Django models.""" -from typing import Any, reveal_type +from typing import Any from django.db.models import Manager, QuerySet from django.db.models.fields.files import FieldFile @@ -21,11 +21,9 @@ def _convert_result( ) -> Result: """Convert the result to a serializable format.""" if isinstance(result, Manager): - print("MANAGER", result) return list(result.all()) if isinstance(result, getattr(QuerySet, "__origin__", QuerySet)): - print("QUERYSET") return list(result) if callable(result): @@ -53,6 +51,7 @@ def _get_prefetched_values(self, key: str) -> Result: "some_key__id": 1, "some_key__name": "Some Name", } + """ values = {} for k, v in self._obj.items(): @@ -65,12 +64,6 @@ def __init__(self, obj: Any, schema_cls: Any, context: Any = None) -> None: self._obj = obj self._schema_cls = schema_cls self._context = context - print("OBJ", self._obj) - reveal_type(self._obj) - print(type(self._obj)) - print("SCHEMA", self._schema_cls) - reveal_type(self._schema_cls) - print(type(self._schema_cls)) def __getattr__(self, key: str) -> Result: """Get the attribute from the object.""" @@ -85,16 +78,12 @@ def __getattr__(self, key: str) -> Result: if isinstance(self._obj, dict): if key not in self._obj: return self._get_prefetched_values(key) - print(f"Key {key} not found in {self._obj}") raise AttributeError(key) value = self._obj[key] else: try: value = getattr(self._obj, key) except AttributeError as e: - print(f"AttributeError: {e}") raise AttributeError(key) from e - print(f"{key} -> {value}") - return self._convert_result(value) diff --git a/django2pydantic/mixin.py b/django2pydantic/mixin.py index 2ad61e8..1a480fe 100644 --- a/django2pydantic/mixin.py +++ b/django2pydantic/mixin.py @@ -30,6 +30,5 @@ def _run_root_validator( info: ValidationInfo, ) -> SVar: """Run the root validator.""" - print("-----------Root Validator-----------") values = DjangoGetter(values, cls, info.context) return handler(values) diff --git a/django2pydantic/schema.py b/django2pydantic/schema.py index 3751118..1619482 100644 --- a/django2pydantic/schema.py +++ b/django2pydantic/schema.py @@ -10,16 +10,14 @@ from django2pydantic.getter import DjangoGetter from django2pydantic.types import ModelFields -S = TypeVar("S", bound=BaseModel) +SType = TypeVar("SType", bound=BaseModel) DictStrAny = dict[str, Any] -class django2pydantic(BaseModel, metaclass=SuperSchemaResolver): +class Schema(BaseModel, metaclass=SuperSchemaResolver): """django2pydantic class.""" - # model_config = ConfigDict(from_attributes=True) - class Config: """Pydantic configuration.""" @@ -38,29 +36,12 @@ class Meta: def _run_root_validator( cls, values: Any, - handler: ModelWrapValidatorHandler[S], + handler: ModelWrapValidatorHandler[SType], info: ValidationInfo, - ) -> S: - print("z--x-------Root Validator-----------") - print("Values", values) - print("Handler", handler) - print("Info", info) - print("end rv") + ) -> SType: forbids_extra = cls.model_config.get("extra") == "forbid" should_validate_assignment = cls.model_config.get("validate_assignment", False) if forbids_extra or should_validate_assignment: handler(values) values = DjangoGetter(obj=values, schema_cls=cls, context=info.context) return handler(values) - - """ - @model_validator(mode="before") - @classmethod - def _run_root_validator( - cls, - values: Any, - info: ValidationInfo, - ) -> DjangoGetter: - print("-----------Root Validator-----------") - return DjangoGetter(values, cls, info.context) - """ diff --git a/examples.ipynb b/examples.ipynb index d81e64a..433701c 100644 --- a/examples.ipynb +++ b/examples.ipynb @@ -1,384 +1,385 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Lets define some example Django models to work with:" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import os\n", - "import django\n", - "\n", - "os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'tests.settings')\n", - "\n", - "# Setup Django\n", - "django.setup()\n", - "\n", - "from django.contrib.auth.models import User\n", - "from django.db import models\n", - "\n", - "\n", - "class Author(models.Model):\n", - " name = models.CharField(max_length=100)\n", - " birth_date = models.DateField()\n", - "\n", - " class Meta:\n", - " app_label = \"tests\"\n", - "\n", - "class Publisher(models.Model):\n", - " name = models.CharField(max_length=100)\n", - " address = models.TextField(help_text=\"Publisher's official address\")\n", - "\n", - " class Meta:\n", - " app_label = \"tests\"\n", - "\n", - "\n", - "class Book(models.Model):\n", - " title = models.CharField(max_length=200)\n", - " isbn = models.CharField(max_length=13, unique=True)\n", - " publication_date = models.DateField()\n", - " authors = models.ManyToManyField(Author) # Many-to-Many relationship\n", - " publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE) # Foreign Key relationship\n", - "\n", - " class Meta:\n", - " app_label = \"tests\"\n", - " default_related_name = 'books'\n", - "\n", - "\n", - "class Library(models.Model):\n", - " name = models.CharField(max_length=100)\n", - " address = models.TextField()\n", - "\n", - " class Meta:\n", - " app_label = \"tests\"\n", - "\n", - "\n", - "class BookCopy(models.Model):\n", - " book = models.ForeignKey(Book, on_delete=models.CASCADE) # Foreign Key relationship\n", - " library = models.ForeignKey(Library, on_delete=models.CASCADE) # Foreign Key relationship\n", - " inventory_number = models.CharField(max_length=20, unique=True)\n", - "\n", - " class Meta:\n", - " app_label = \"tests\"\n", - " default_related_name = \"book_copies\"\n", - "\n", - "\n", - "class Borrowing(models.Model):\n", - " user = models.ForeignKey(User, on_delete=models.CASCADE) # Foreign Key relationship\n", - " book_copy = models.ForeignKey(BookCopy, on_delete=models.CASCADE) # Foreign Key relationship\n", - " borrow_date = models.DateField()\n", - " return_date = models.DateField(null=True, blank=True)\n", - "\n", - " class Meta:\n", - " app_label = \"tests\"\n", - " default_related_name = 'borrowings'\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now lets do some testing:" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
{\n", - " \"$defs\": {\n", - " \"None_authors\": {\n", - " \"properties\": {\n", - " \"name\": {\n", - " \"description\": \"Name\",\n", - " \"maxLength\": 100,\n", - " \"title\": \"Name\",\n", - " \"type\": \"string\"\n", - " }\n", - " },\n", - " \"required\": [\n", - " \"name\"\n", - " ],\n", - " \"title\": \"None_authors\",\n", - " \"type\": \"object\"\n", - " },\n", - " \"None_book_copies\": {\n", - " \"properties\": {\n", - " \"library\": {\n", - " \"description\": \"Library\",\n", - " \"title\": \"Library\",\n", - " \"type\": \"integer\"\n", - " }\n", - " },\n", - " \"required\": [\n", - " \"library\"\n", - " ],\n", - " \"title\": \"None_book_copies\",\n", - " \"type\": \"object\"\n", - " },\n", - " \"None_publisher\": {\n", - " \"properties\": {\n", - " \"name\": {\n", - " \"description\": \"Name\",\n", - " \"maxLength\": 100,\n", - " \"title\": \"Name\",\n", - " \"type\": \"string\"\n", - " }\n", - " },\n", - " \"required\": [\n", - " \"name\"\n", - " ],\n", - " \"title\": \"None_publisher\",\n", - " \"type\": \"object\"\n", - " }\n", - " },\n", - " \"properties\": {\n", - " \"title\": {\n", - " \"description\": \"Title\",\n", - " \"maxLength\": 200,\n", - " \"title\": \"Title\",\n", - " \"type\": \"string\"\n", - " },\n", - " \"isbn\": {\n", - " \"description\": \"Isbn\",\n", - " \"maxLength\": 13,\n", - " \"title\": \"Isbn\",\n", - " \"type\": \"string\"\n", - " },\n", - " \"publication_date\": {\n", - " \"description\": \"Publication Date\",\n", - " \"format\": \"date\",\n", - " \"title\": \"Publication Date\",\n", - " \"type\": \"string\"\n", - " },\n", - " \"authors\": {\n", - " \"anyOf\": [\n", - " {\n", - " \"items\": {\n", - " \"$ref\": \"#/$defs/None_authors\"\n", - " },\n", - " \"type\": \"array\"\n", - " },\n", - " {\n", - " \"type\": \"null\"\n", - " }\n", - " ],\n", - " \"default\": null,\n", - " \"description\": \"authors\",\n", - " \"title\": \"authors\"\n", - " },\n", - " \"publisher\": {\n", - " \"$ref\": \"#/$defs/None_publisher\",\n", - " \"description\": \"publisher\",\n", - " \"title\": \"publisher\"\n", - " },\n", - " \"book_copies\": {\n", - " \"anyOf\": [\n", - " {\n", - " \"items\": {\n", - " \"$ref\": \"#/$defs/None_book_copies\"\n", - " },\n", - " \"type\": \"array\"\n", - " },\n", - " {\n", - " \"type\": \"null\"\n", - " }\n", - " ],\n", - " \"default\": null,\n", - " \"description\": \"book_copies\",\n", - " \"title\": \"book_copies\"\n", - " }\n", - " },\n", - " \"required\": [\n", - " \"title\",\n", - " \"isbn\",\n", - " \"publication_date\",\n", - " \"publisher\"\n", - " ],\n", - " \"title\": \"BookSchema\",\n", - " \"type\": \"object\"\n", - "}\n", - "\n" - ], - "text/plain": [ - "\u001b[1m{\u001b[0m\n", - " \u001b[1;34m\"$defs\"\u001b[0m: \u001b[1m{\u001b[0m\n", - " \u001b[1;34m\"None_authors\"\u001b[0m: \u001b[1m{\u001b[0m\n", - " \u001b[1;34m\"properties\"\u001b[0m: \u001b[1m{\u001b[0m\n", - " \u001b[1;34m\"name\"\u001b[0m: \u001b[1m{\u001b[0m\n", - " \u001b[1;34m\"description\"\u001b[0m: \u001b[32m\"Name\"\u001b[0m,\n", - " \u001b[1;34m\"maxLength\"\u001b[0m: \u001b[1;36m100\u001b[0m,\n", - " \u001b[1;34m\"title\"\u001b[0m: \u001b[32m\"Name\"\u001b[0m,\n", - " \u001b[1;34m\"type\"\u001b[0m: \u001b[32m\"string\"\u001b[0m\n", - " \u001b[1m}\u001b[0m\n", - " \u001b[1m}\u001b[0m,\n", - " \u001b[1;34m\"required\"\u001b[0m: \u001b[1m[\u001b[0m\n", - " \u001b[32m\"name\"\u001b[0m\n", - " \u001b[1m]\u001b[0m,\n", - " \u001b[1;34m\"title\"\u001b[0m: \u001b[32m\"None_authors\"\u001b[0m,\n", - " \u001b[1;34m\"type\"\u001b[0m: \u001b[32m\"object\"\u001b[0m\n", - " \u001b[1m}\u001b[0m,\n", - " \u001b[1;34m\"None_book_copies\"\u001b[0m: \u001b[1m{\u001b[0m\n", - " \u001b[1;34m\"properties\"\u001b[0m: \u001b[1m{\u001b[0m\n", - " \u001b[1;34m\"library\"\u001b[0m: \u001b[1m{\u001b[0m\n", - " \u001b[1;34m\"description\"\u001b[0m: \u001b[32m\"Library\"\u001b[0m,\n", - " \u001b[1;34m\"title\"\u001b[0m: \u001b[32m\"Library\"\u001b[0m,\n", - " \u001b[1;34m\"type\"\u001b[0m: \u001b[32m\"integer\"\u001b[0m\n", - " \u001b[1m}\u001b[0m\n", - " \u001b[1m}\u001b[0m,\n", - " \u001b[1;34m\"required\"\u001b[0m: \u001b[1m[\u001b[0m\n", - " \u001b[32m\"library\"\u001b[0m\n", - " \u001b[1m]\u001b[0m,\n", - " \u001b[1;34m\"title\"\u001b[0m: \u001b[32m\"None_book_copies\"\u001b[0m,\n", - " \u001b[1;34m\"type\"\u001b[0m: \u001b[32m\"object\"\u001b[0m\n", - " \u001b[1m}\u001b[0m,\n", - " \u001b[1;34m\"None_publisher\"\u001b[0m: \u001b[1m{\u001b[0m\n", - " \u001b[1;34m\"properties\"\u001b[0m: \u001b[1m{\u001b[0m\n", - " \u001b[1;34m\"name\"\u001b[0m: \u001b[1m{\u001b[0m\n", - " \u001b[1;34m\"description\"\u001b[0m: \u001b[32m\"Name\"\u001b[0m,\n", - " \u001b[1;34m\"maxLength\"\u001b[0m: \u001b[1;36m100\u001b[0m,\n", - " \u001b[1;34m\"title\"\u001b[0m: \u001b[32m\"Name\"\u001b[0m,\n", - " \u001b[1;34m\"type\"\u001b[0m: \u001b[32m\"string\"\u001b[0m\n", - " \u001b[1m}\u001b[0m\n", - " \u001b[1m}\u001b[0m,\n", - " \u001b[1;34m\"required\"\u001b[0m: \u001b[1m[\u001b[0m\n", - " \u001b[32m\"name\"\u001b[0m\n", - " \u001b[1m]\u001b[0m,\n", - " \u001b[1;34m\"title\"\u001b[0m: \u001b[32m\"None_publisher\"\u001b[0m,\n", - " \u001b[1;34m\"type\"\u001b[0m: \u001b[32m\"object\"\u001b[0m\n", - " \u001b[1m}\u001b[0m\n", - " \u001b[1m}\u001b[0m,\n", - " \u001b[1;34m\"properties\"\u001b[0m: \u001b[1m{\u001b[0m\n", - " \u001b[1;34m\"title\"\u001b[0m: \u001b[1m{\u001b[0m\n", - " \u001b[1;34m\"description\"\u001b[0m: \u001b[32m\"Title\"\u001b[0m,\n", - " \u001b[1;34m\"maxLength\"\u001b[0m: \u001b[1;36m200\u001b[0m,\n", - " \u001b[1;34m\"title\"\u001b[0m: \u001b[32m\"Title\"\u001b[0m,\n", - " \u001b[1;34m\"type\"\u001b[0m: \u001b[32m\"string\"\u001b[0m\n", - " \u001b[1m}\u001b[0m,\n", - " \u001b[1;34m\"isbn\"\u001b[0m: \u001b[1m{\u001b[0m\n", - " \u001b[1;34m\"description\"\u001b[0m: \u001b[32m\"Isbn\"\u001b[0m,\n", - " \u001b[1;34m\"maxLength\"\u001b[0m: \u001b[1;36m13\u001b[0m,\n", - " \u001b[1;34m\"title\"\u001b[0m: \u001b[32m\"Isbn\"\u001b[0m,\n", - " \u001b[1;34m\"type\"\u001b[0m: \u001b[32m\"string\"\u001b[0m\n", - " \u001b[1m}\u001b[0m,\n", - " \u001b[1;34m\"publication_date\"\u001b[0m: \u001b[1m{\u001b[0m\n", - " \u001b[1;34m\"description\"\u001b[0m: \u001b[32m\"Publication Date\"\u001b[0m,\n", - " \u001b[1;34m\"format\"\u001b[0m: \u001b[32m\"date\"\u001b[0m,\n", - " \u001b[1;34m\"title\"\u001b[0m: \u001b[32m\"Publication Date\"\u001b[0m,\n", - " \u001b[1;34m\"type\"\u001b[0m: \u001b[32m\"string\"\u001b[0m\n", - " \u001b[1m}\u001b[0m,\n", - " \u001b[1;34m\"authors\"\u001b[0m: \u001b[1m{\u001b[0m\n", - " \u001b[1;34m\"anyOf\"\u001b[0m: \u001b[1m[\u001b[0m\n", - " \u001b[1m{\u001b[0m\n", - " \u001b[1;34m\"items\"\u001b[0m: \u001b[1m{\u001b[0m\n", - " \u001b[1;34m\"$ref\"\u001b[0m: \u001b[32m\"#/$defs/None_authors\"\u001b[0m\n", - " \u001b[1m}\u001b[0m,\n", - " \u001b[1;34m\"type\"\u001b[0m: \u001b[32m\"array\"\u001b[0m\n", - " \u001b[1m}\u001b[0m,\n", - " \u001b[1m{\u001b[0m\n", - " \u001b[1;34m\"type\"\u001b[0m: \u001b[32m\"null\"\u001b[0m\n", - " \u001b[1m}\u001b[0m\n", - " \u001b[1m]\u001b[0m,\n", - " \u001b[1;34m\"default\"\u001b[0m: \u001b[3;35mnull\u001b[0m,\n", - " \u001b[1;34m\"description\"\u001b[0m: \u001b[32m\"authors\"\u001b[0m,\n", - " \u001b[1;34m\"title\"\u001b[0m: \u001b[32m\"authors\"\u001b[0m\n", - " \u001b[1m}\u001b[0m,\n", - " \u001b[1;34m\"publisher\"\u001b[0m: \u001b[1m{\u001b[0m\n", - " \u001b[1;34m\"$ref\"\u001b[0m: \u001b[32m\"#/$defs/None_publisher\"\u001b[0m,\n", - " \u001b[1;34m\"description\"\u001b[0m: \u001b[32m\"publisher\"\u001b[0m,\n", - " \u001b[1;34m\"title\"\u001b[0m: \u001b[32m\"publisher\"\u001b[0m\n", - " \u001b[1m}\u001b[0m,\n", - " \u001b[1;34m\"book_copies\"\u001b[0m: \u001b[1m{\u001b[0m\n", - " \u001b[1;34m\"anyOf\"\u001b[0m: \u001b[1m[\u001b[0m\n", - " \u001b[1m{\u001b[0m\n", - " \u001b[1;34m\"items\"\u001b[0m: \u001b[1m{\u001b[0m\n", - " \u001b[1;34m\"$ref\"\u001b[0m: \u001b[32m\"#/$defs/None_book_copies\"\u001b[0m\n", - " \u001b[1m}\u001b[0m,\n", - " \u001b[1;34m\"type\"\u001b[0m: \u001b[32m\"array\"\u001b[0m\n", - " \u001b[1m}\u001b[0m,\n", - " \u001b[1m{\u001b[0m\n", - " \u001b[1;34m\"type\"\u001b[0m: \u001b[32m\"null\"\u001b[0m\n", - " \u001b[1m}\u001b[0m\n", - " \u001b[1m]\u001b[0m,\n", - " \u001b[1;34m\"default\"\u001b[0m: \u001b[3;35mnull\u001b[0m,\n", - " \u001b[1;34m\"description\"\u001b[0m: \u001b[32m\"book_copies\"\u001b[0m,\n", - " \u001b[1;34m\"title\"\u001b[0m: \u001b[32m\"book_copies\"\u001b[0m\n", - " \u001b[1m}\u001b[0m\n", - " \u001b[1m}\u001b[0m,\n", - " \u001b[1;34m\"required\"\u001b[0m: \u001b[1m[\u001b[0m\n", - " \u001b[32m\"title\"\u001b[0m,\n", - " \u001b[32m\"isbn\"\u001b[0m,\n", - " \u001b[32m\"publication_date\"\u001b[0m,\n", - " \u001b[32m\"publisher\"\u001b[0m\n", - " \u001b[1m]\u001b[0m,\n", - " \u001b[1;34m\"title\"\u001b[0m: \u001b[32m\"BookSchema\"\u001b[0m,\n", - " \u001b[1;34m\"type\"\u001b[0m: \u001b[32m\"object\"\u001b[0m\n", - "\u001b[1m}\u001b[0m\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "from typing import ClassVar\n", - "\n", - "from django2pydantic.schema import django2pydantic\n", - "from django2pydantic.types import Infer, ModelFields\n", - "from rich import print_json\n", - "\n", - "class BookSchema(django2pydantic):\n", - " \"\"\"Book schema example with nested fields.\"\"\"\n", - "\n", - " class Meta(django2pydantic.Meta):\n", - " \"\"\"Here we define the model and the fields we want to infer.\"\"\"\n", - "\n", - " model = Book\n", - " fields: ClassVar[ModelFields] = {\n", - " \"title\": Infer,\n", - " \"isbn\": Infer,\n", - " \"publication_date\": Infer,\n", - " \"authors\": {\"name\": Infer},\n", - " \"publisher\": {\"name\": Infer},\n", - " \"book_copies\": {\"library\": Infer}, # note: here we use a reverse relation\n", - " }\n", - "\n", - "print_json(data=BookSchema.model_json_schema())\n", - "\n" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.7" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} \ No newline at end of file + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Lets define some example Django models to work with:" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import django\n", + "\n", + "os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'tests.settings')\n", + "\n", + "# Setup Django\n", + "django.setup()\n", + "\n", + "from django.contrib.auth.models import User\n", + "from django.db import models\n", + "\n", + "\n", + "class Author(models.Model):\n", + " name = models.CharField(max_length=100)\n", + " birth_date = models.DateField()\n", + "\n", + " class Meta:\n", + " app_label = \"tests\"\n", + "\n", + "class Publisher(models.Model):\n", + " name = models.CharField(max_length=100)\n", + " address = models.TextField(help_text=\"Publisher's official address\")\n", + "\n", + " class Meta:\n", + " app_label = \"tests\"\n", + "\n", + "\n", + "class Book(models.Model):\n", + " title = models.CharField(max_length=200)\n", + " isbn = models.CharField(max_length=13, unique=True)\n", + " publication_date = models.DateField()\n", + " authors = models.ManyToManyField(Author) # Many-to-Many relationship\n", + " publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE) # Foreign Key relationship\n", + "\n", + " class Meta:\n", + " app_label = \"tests\"\n", + " default_related_name = 'books'\n", + "\n", + "\n", + "class Library(models.Model):\n", + " name = models.CharField(max_length=100)\n", + " address = models.TextField()\n", + "\n", + " class Meta:\n", + " app_label = \"tests\"\n", + "\n", + "\n", + "class BookCopy(models.Model):\n", + " book = models.ForeignKey(Book, on_delete=models.CASCADE) # Foreign Key relationship\n", + " library = models.ForeignKey(Library, on_delete=models.CASCADE) # Foreign Key relationship\n", + " inventory_number = models.CharField(max_length=20, unique=True)\n", + "\n", + " class Meta:\n", + " app_label = \"tests\"\n", + " default_related_name = \"book_copies\"\n", + "\n", + "\n", + "class Borrowing(models.Model):\n", + " user = models.ForeignKey(User, on_delete=models.CASCADE) # Foreign Key relationship\n", + " book_copy = models.ForeignKey(BookCopy, on_delete=models.CASCADE) # Foreign Key relationship\n", + " borrow_date = models.DateField()\n", + " return_date = models.DateField(null=True, blank=True)\n", + "\n", + " class Meta:\n", + " app_label = \"tests\"\n", + " default_related_name = 'borrowings'\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now lets do some testing:" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
{\n", + " \"$defs\": {\n", + " \"None_authors\": {\n", + " \"properties\": {\n", + " \"name\": {\n", + " \"description\": \"Name\",\n", + " \"maxLength\": 100,\n", + " \"title\": \"Name\",\n", + " \"type\": \"string\"\n", + " }\n", + " },\n", + " \"required\": [\n", + " \"name\"\n", + " ],\n", + " \"title\": \"None_authors\",\n", + " \"type\": \"object\"\n", + " },\n", + " \"None_book_copies\": {\n", + " \"properties\": {\n", + " \"library\": {\n", + " \"description\": \"Library\",\n", + " \"title\": \"Library\",\n", + " \"type\": \"integer\"\n", + " }\n", + " },\n", + " \"required\": [\n", + " \"library\"\n", + " ],\n", + " \"title\": \"None_book_copies\",\n", + " \"type\": \"object\"\n", + " },\n", + " \"None_publisher\": {\n", + " \"properties\": {\n", + " \"name\": {\n", + " \"description\": \"Name\",\n", + " \"maxLength\": 100,\n", + " \"title\": \"Name\",\n", + " \"type\": \"string\"\n", + " }\n", + " },\n", + " \"required\": [\n", + " \"name\"\n", + " ],\n", + " \"title\": \"None_publisher\",\n", + " \"type\": \"object\"\n", + " }\n", + " },\n", + " \"properties\": {\n", + " \"title\": {\n", + " \"description\": \"Title\",\n", + " \"maxLength\": 200,\n", + " \"title\": \"Title\",\n", + " \"type\": \"string\"\n", + " },\n", + " \"isbn\": {\n", + " \"description\": \"Isbn\",\n", + " \"maxLength\": 13,\n", + " \"title\": \"Isbn\",\n", + " \"type\": \"string\"\n", + " },\n", + " \"publication_date\": {\n", + " \"description\": \"Publication Date\",\n", + " \"format\": \"date\",\n", + " \"title\": \"Publication Date\",\n", + " \"type\": \"string\"\n", + " },\n", + " \"authors\": {\n", + " \"anyOf\": [\n", + " {\n", + " \"items\": {\n", + " \"$ref\": \"#/$defs/None_authors\"\n", + " },\n", + " \"type\": \"array\"\n", + " },\n", + " {\n", + " \"type\": \"null\"\n", + " }\n", + " ],\n", + " \"default\": null,\n", + " \"description\": \"authors\",\n", + " \"title\": \"authors\"\n", + " },\n", + " \"publisher\": {\n", + " \"$ref\": \"#/$defs/None_publisher\",\n", + " \"description\": \"publisher\",\n", + " \"title\": \"publisher\"\n", + " },\n", + " \"book_copies\": {\n", + " \"anyOf\": [\n", + " {\n", + " \"items\": {\n", + " \"$ref\": \"#/$defs/None_book_copies\"\n", + " },\n", + " \"type\": \"array\"\n", + " },\n", + " {\n", + " \"type\": \"null\"\n", + " }\n", + " ],\n", + " \"default\": null,\n", + " \"description\": \"book_copies\",\n", + " \"title\": \"book_copies\"\n", + " }\n", + " },\n", + " \"required\": [\n", + " \"title\",\n", + " \"isbn\",\n", + " \"publication_date\",\n", + " \"publisher\"\n", + " ],\n", + " \"title\": \"BookSchema\",\n", + " \"type\": \"object\"\n", + "}\n", + "\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"$defs\"\u001b[0m: \u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"None_authors\"\u001b[0m: \u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"properties\"\u001b[0m: \u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"name\"\u001b[0m: \u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"description\"\u001b[0m: \u001b[32m\"Name\"\u001b[0m,\n", + " \u001b[1;34m\"maxLength\"\u001b[0m: \u001b[1;36m100\u001b[0m,\n", + " \u001b[1;34m\"title\"\u001b[0m: \u001b[32m\"Name\"\u001b[0m,\n", + " \u001b[1;34m\"type\"\u001b[0m: \u001b[32m\"string\"\u001b[0m\n", + " \u001b[1m}\u001b[0m\n", + " \u001b[1m}\u001b[0m,\n", + " \u001b[1;34m\"required\"\u001b[0m: \u001b[1m[\u001b[0m\n", + " \u001b[32m\"name\"\u001b[0m\n", + " \u001b[1m]\u001b[0m,\n", + " \u001b[1;34m\"title\"\u001b[0m: \u001b[32m\"None_authors\"\u001b[0m,\n", + " \u001b[1;34m\"type\"\u001b[0m: \u001b[32m\"object\"\u001b[0m\n", + " \u001b[1m}\u001b[0m,\n", + " \u001b[1;34m\"None_book_copies\"\u001b[0m: \u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"properties\"\u001b[0m: \u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"library\"\u001b[0m: \u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"description\"\u001b[0m: \u001b[32m\"Library\"\u001b[0m,\n", + " \u001b[1;34m\"title\"\u001b[0m: \u001b[32m\"Library\"\u001b[0m,\n", + " \u001b[1;34m\"type\"\u001b[0m: \u001b[32m\"integer\"\u001b[0m\n", + " \u001b[1m}\u001b[0m\n", + " \u001b[1m}\u001b[0m,\n", + " \u001b[1;34m\"required\"\u001b[0m: \u001b[1m[\u001b[0m\n", + " \u001b[32m\"library\"\u001b[0m\n", + " \u001b[1m]\u001b[0m,\n", + " \u001b[1;34m\"title\"\u001b[0m: \u001b[32m\"None_book_copies\"\u001b[0m,\n", + " \u001b[1;34m\"type\"\u001b[0m: \u001b[32m\"object\"\u001b[0m\n", + " \u001b[1m}\u001b[0m,\n", + " \u001b[1;34m\"None_publisher\"\u001b[0m: \u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"properties\"\u001b[0m: \u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"name\"\u001b[0m: \u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"description\"\u001b[0m: \u001b[32m\"Name\"\u001b[0m,\n", + " \u001b[1;34m\"maxLength\"\u001b[0m: \u001b[1;36m100\u001b[0m,\n", + " \u001b[1;34m\"title\"\u001b[0m: \u001b[32m\"Name\"\u001b[0m,\n", + " \u001b[1;34m\"type\"\u001b[0m: \u001b[32m\"string\"\u001b[0m\n", + " \u001b[1m}\u001b[0m\n", + " \u001b[1m}\u001b[0m,\n", + " \u001b[1;34m\"required\"\u001b[0m: \u001b[1m[\u001b[0m\n", + " \u001b[32m\"name\"\u001b[0m\n", + " \u001b[1m]\u001b[0m,\n", + " \u001b[1;34m\"title\"\u001b[0m: \u001b[32m\"None_publisher\"\u001b[0m,\n", + " \u001b[1;34m\"type\"\u001b[0m: \u001b[32m\"object\"\u001b[0m\n", + " \u001b[1m}\u001b[0m\n", + " \u001b[1m}\u001b[0m,\n", + " \u001b[1;34m\"properties\"\u001b[0m: \u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"title\"\u001b[0m: \u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"description\"\u001b[0m: \u001b[32m\"Title\"\u001b[0m,\n", + " \u001b[1;34m\"maxLength\"\u001b[0m: \u001b[1;36m200\u001b[0m,\n", + " \u001b[1;34m\"title\"\u001b[0m: \u001b[32m\"Title\"\u001b[0m,\n", + " \u001b[1;34m\"type\"\u001b[0m: \u001b[32m\"string\"\u001b[0m\n", + " \u001b[1m}\u001b[0m,\n", + " \u001b[1;34m\"isbn\"\u001b[0m: \u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"description\"\u001b[0m: \u001b[32m\"Isbn\"\u001b[0m,\n", + " \u001b[1;34m\"maxLength\"\u001b[0m: \u001b[1;36m13\u001b[0m,\n", + " \u001b[1;34m\"title\"\u001b[0m: \u001b[32m\"Isbn\"\u001b[0m,\n", + " \u001b[1;34m\"type\"\u001b[0m: \u001b[32m\"string\"\u001b[0m\n", + " \u001b[1m}\u001b[0m,\n", + " \u001b[1;34m\"publication_date\"\u001b[0m: \u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"description\"\u001b[0m: \u001b[32m\"Publication Date\"\u001b[0m,\n", + " \u001b[1;34m\"format\"\u001b[0m: \u001b[32m\"date\"\u001b[0m,\n", + " \u001b[1;34m\"title\"\u001b[0m: \u001b[32m\"Publication Date\"\u001b[0m,\n", + " \u001b[1;34m\"type\"\u001b[0m: \u001b[32m\"string\"\u001b[0m\n", + " \u001b[1m}\u001b[0m,\n", + " \u001b[1;34m\"authors\"\u001b[0m: \u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"anyOf\"\u001b[0m: \u001b[1m[\u001b[0m\n", + " \u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"items\"\u001b[0m: \u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"$ref\"\u001b[0m: \u001b[32m\"#/$defs/None_authors\"\u001b[0m\n", + " \u001b[1m}\u001b[0m,\n", + " \u001b[1;34m\"type\"\u001b[0m: \u001b[32m\"array\"\u001b[0m\n", + " \u001b[1m}\u001b[0m,\n", + " \u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"type\"\u001b[0m: \u001b[32m\"null\"\u001b[0m\n", + " \u001b[1m}\u001b[0m\n", + " \u001b[1m]\u001b[0m,\n", + " \u001b[1;34m\"default\"\u001b[0m: \u001b[3;35mnull\u001b[0m,\n", + " \u001b[1;34m\"description\"\u001b[0m: \u001b[32m\"authors\"\u001b[0m,\n", + " \u001b[1;34m\"title\"\u001b[0m: \u001b[32m\"authors\"\u001b[0m\n", + " \u001b[1m}\u001b[0m,\n", + " \u001b[1;34m\"publisher\"\u001b[0m: \u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"$ref\"\u001b[0m: \u001b[32m\"#/$defs/None_publisher\"\u001b[0m,\n", + " \u001b[1;34m\"description\"\u001b[0m: \u001b[32m\"publisher\"\u001b[0m,\n", + " \u001b[1;34m\"title\"\u001b[0m: \u001b[32m\"publisher\"\u001b[0m\n", + " \u001b[1m}\u001b[0m,\n", + " \u001b[1;34m\"book_copies\"\u001b[0m: \u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"anyOf\"\u001b[0m: \u001b[1m[\u001b[0m\n", + " \u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"items\"\u001b[0m: \u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"$ref\"\u001b[0m: \u001b[32m\"#/$defs/None_book_copies\"\u001b[0m\n", + " \u001b[1m}\u001b[0m,\n", + " \u001b[1;34m\"type\"\u001b[0m: \u001b[32m\"array\"\u001b[0m\n", + " \u001b[1m}\u001b[0m,\n", + " \u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"type\"\u001b[0m: \u001b[32m\"null\"\u001b[0m\n", + " \u001b[1m}\u001b[0m\n", + " \u001b[1m]\u001b[0m,\n", + " \u001b[1;34m\"default\"\u001b[0m: \u001b[3;35mnull\u001b[0m,\n", + " \u001b[1;34m\"description\"\u001b[0m: \u001b[32m\"book_copies\"\u001b[0m,\n", + " \u001b[1;34m\"title\"\u001b[0m: \u001b[32m\"book_copies\"\u001b[0m\n", + " \u001b[1m}\u001b[0m\n", + " \u001b[1m}\u001b[0m,\n", + " \u001b[1;34m\"required\"\u001b[0m: \u001b[1m[\u001b[0m\n", + " \u001b[32m\"title\"\u001b[0m,\n", + " \u001b[32m\"isbn\"\u001b[0m,\n", + " \u001b[32m\"publication_date\"\u001b[0m,\n", + " \u001b[32m\"publisher\"\u001b[0m\n", + " \u001b[1m]\u001b[0m,\n", + " \u001b[1;34m\"title\"\u001b[0m: \u001b[32m\"BookSchema\"\u001b[0m,\n", + " \u001b[1;34m\"type\"\u001b[0m: \u001b[32m\"object\"\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from typing import ClassVar\n", + "\n", + "from rich import print_json\n", + "\n", + "from django2pydantic.schema import Schema\n", + "from django2pydantic.types import Infer, ModelFields\n", + "\n", + "\n", + "class BookSchema(Schema):\n", + " \"\"\"Book schema example with nested fields.\"\"\"\n", + "\n", + " class Meta(Schema.Meta):\n", + " \"\"\"Here we define the model and the fields we want to infer.\"\"\"\n", + "\n", + " model = Book\n", + " fields: ClassVar[ModelFields] = {\n", + " \"title\": Infer,\n", + " \"isbn\": Infer,\n", + " \"publication_date\": Infer,\n", + " \"authors\": {\"name\": Infer},\n", + " \"publisher\": {\"name\": Infer},\n", + " \"book_copies\": {\"library\": Infer}, # note: here we use a reverse relation\n", + " }\n", + "\n", + "print_json(data=BookSchema.model_json_schema())\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/tests/test_basics.py b/tests/test_basics.py index f486ced..b42e427 100644 --- a/tests/test_basics.py +++ b/tests/test_basics.py @@ -10,7 +10,7 @@ from hypothesis import given from hypothesis import strategies as st -from django2pydantic.schema import django2pydantic +from django2pydantic.schema import Schema from django2pydantic.types import Infer, ModelFields from tests.utils import debug_json, get_openapi_schema_from_field @@ -246,10 +246,10 @@ class ModelA(models.Model): id = models.AutoField(primary_key=True) name = models.CharField(max_length=100) - class SchemaA(django2pydantic): + class SchemaA(Schema): """SchemaA class.""" - class Meta(django2pydantic.Meta): + class Meta(Schema.Meta): """Meta class.""" model = ModelA diff --git a/tests/test_choices.py b/tests/test_choices.py index 375386b..7cc6993 100644 --- a/tests/test_choices.py +++ b/tests/test_choices.py @@ -80,7 +80,6 @@ class Choices(models.IntegerChoices): openapi_schema = get_openapi_schema_from_field( models.IntegerField(choices=Choices.choices), ) - # print(openapi_schema) debug_json(openapi_schema) assert openapi_schema["properties"]["field"]["enum"] == Choices.values assert openapi_schema["properties"]["field"]["type"] == "integer" diff --git a/tests/test_error_messages.py b/tests/test_error_messages.py index ce77a14..a344f33 100644 --- a/tests/test_error_messages.py +++ b/tests/test_error_messages.py @@ -5,7 +5,7 @@ import pytest from django.db import models -from django2pydantic.schema import django2pydantic +from django2pydantic.schema import Schema from django2pydantic.types import Infer, ModelFields @@ -16,10 +16,10 @@ def test_defing_a_non_existing_field_raises_exception() -> None: class ModelA(models.Model): # noqa: DJ008 id = models.AutoField(primary_key=True) - class SchemaA(django2pydantic): + class SchemaA(Schema): """SchemaA class.""" - class Meta(django2pydantic.Meta): + class Meta(Schema.Meta): """Meta class.""" model = ModelA diff --git a/tests/test_id_fields.py b/tests/test_id_fields.py index 02f827f..286f047 100644 --- a/tests/test_id_fields.py +++ b/tests/test_id_fields.py @@ -5,7 +5,7 @@ from django.db import models from pydantic.v1.fields import ModelField -from django2pydantic.schema import django2pydantic +from django2pydantic.schema import Schema from django2pydantic.types import Infer from tests.utils import debug_json @@ -16,10 +16,10 @@ def test_implicit_id_fields_works() -> None: class ModelA(models.Model): name = models.CharField(max_length=100) - class SchemaA(django2pydantic): + class SchemaA(Schema): """SchemaA class.""" - class Meta(django2pydantic.Meta): + class Meta(Schema.Meta): """Meta class.""" model = ModelA @@ -41,10 +41,10 @@ class ModelA(models.Model): id = models.AutoField(primary_key=True) name = models.CharField(max_length=100) - class SchemaA(django2pydantic): + class SchemaA(Schema): """SchemaA class.""" - class Meta(django2pydantic.Meta): + class Meta(Schema.Meta): """Meta class.""" model = ModelA diff --git a/tests/test_property_method_fields.py b/tests/test_property_method_fields.py index 05ca086..aca6973 100644 --- a/tests/test_property_method_fields.py +++ b/tests/test_property_method_fields.py @@ -5,7 +5,7 @@ import pytest from django.db import models -from django2pydantic.schema import django2pydantic +from django2pydantic.schema import Schema from django2pydantic.types import Infer, ModelFields from tests.utils import add_property_method, debug_json, get_openapi_equivalent @@ -35,10 +35,10 @@ class ModelA(models.Model): value="test", ) - class SchemaA(django2pydantic): + class SchemaA(Schema): """SchemaA class.""" - class Meta(django2pydantic.Meta): + class Meta(Schema.Meta): """Meta class.""" model = ModelA diff --git a/tests/test_relations_are_supported.py b/tests/test_relations_are_supported.py index 4849909..175fc9f 100644 --- a/tests/test_relations_are_supported.py +++ b/tests/test_relations_are_supported.py @@ -3,7 +3,7 @@ from django.db import models -from django2pydantic.schema import django2pydantic +from django2pydantic.schema import Schema from django2pydantic.types import Infer, ModelFields from tests.utils import debug_json, django_model_factory, get_openapi_schema_from_field @@ -40,10 +40,10 @@ class ModelB(models.Model): name = models.CharField(max_length=100) rel_a = models.ForeignKey(ModelA, on_delete=models.CASCADE) - class SchemaB(django2pydantic): + class SchemaB(Schema): """SchemaB class.""" - class Meta(django2pydantic.Meta): + class Meta(Schema.Meta): """Meta class.""" model = ModelB @@ -75,10 +75,10 @@ class ModelB(models.Model): name = models.CharField(max_length=100) rel_a = models.ForeignKey(ModelA, on_delete=models.CASCADE, to_field="var") - class SchemaB(django2pydantic): + class SchemaB(Schema): """SchemaB class.""" - class Meta(django2pydantic.Meta): + class Meta(Schema.Meta): """Meta class.""" model = ModelB @@ -110,10 +110,10 @@ class ModelB(models.Model): name = models.CharField(max_length=100) rel_a = models.ManyToManyField(ModelA) - class SchemaB(django2pydantic): + class SchemaB(Schema): """SchemaB class.""" - class Meta(django2pydantic.Meta): + class Meta(Schema.Meta): """Meta class.""" model = ModelB @@ -151,10 +151,10 @@ class ModelB(models.Model): name = models.CharField(max_length=100) rel_a = models.OneToOneField(ModelA, on_delete=models.CASCADE) - class SchemaB(django2pydantic): + class SchemaB(Schema): """SchemaB class.""" - class Meta(django2pydantic.Meta): + class Meta(Schema.Meta): """Meta class.""" model = ModelB @@ -189,10 +189,10 @@ class ModelB(models.Model): class Meta: default_related_name = "rel_b" - class SchemaA(django2pydantic): + class SchemaA(Schema): """SchemaA class.""" - class Meta(django2pydantic.Meta): + class Meta(Schema.Meta): """Meta class.""" model = ModelB @@ -227,10 +227,10 @@ class ModelB(models.Model): class Meta: default_related_name = "rel_b" - class SchemaA(django2pydantic): + class SchemaA(Schema): """SchemaA class.""" - class Meta(django2pydantic.Meta): + class Meta(Schema.Meta): """Meta class.""" model = ModelA @@ -265,10 +265,10 @@ class ModelB(models.Model): class Meta: default_related_name = "rel_b" - class SchemaA(django2pydantic): + class SchemaA(Schema): """SchemaA class.""" - class Meta(django2pydantic.Meta): + class Meta(Schema.Meta): """Meta class.""" model = ModelB @@ -300,10 +300,10 @@ class ModelB(models.Model): name = models.CharField(max_length=100) rel_a = models.ForeignKey(ModelA, on_delete=models.CASCADE) - class SchemaB(django2pydantic): + class SchemaB(Schema): """SchemaB class.""" - class Meta(django2pydantic.Meta): + class Meta(Schema.Meta): """Meta class.""" model = ModelB @@ -327,10 +327,10 @@ class ModelA(models.Model): name = models.CharField(max_length=100) rel_a = models.ManyToManyField("self", symmetrical=True) - class SchemaA(django2pydantic): + class SchemaA(Schema): """SchemaA class.""" - class Meta(django2pydantic.Meta): + class Meta(Schema.Meta): """Meta class.""" model = ModelA @@ -362,10 +362,10 @@ class ModelB(models.Model): name = models.CharField(max_length=100) rel_a = models.ManyToManyField(ModelA) - class SchemaB(django2pydantic): + class SchemaB(Schema): """SchemaB class.""" - class Meta(django2pydantic.Meta): + class Meta(Schema.Meta): """Meta class.""" model = ModelB diff --git a/tests/utils.py b/tests/utils.py index 8385e2c..00d2568 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -9,7 +9,7 @@ from django.db import models from rich import print_json -from django2pydantic.schema import django2pydantic +from django2pydantic.schema import Schema from django2pydantic.types import Infer, MetaFields, ModelFields DjangoField = models.Field[Any, Any] @@ -54,8 +54,8 @@ def pydantic_schema_from_field(field: DjangoField) -> type[pydantic.BaseModel]: meta_class = type("Meta", (), dict(meta_class_attrs)) return type( - "Schema", - (django2pydantic,), + "TestSchema", + (Schema,), { "Meta": meta_class, },