tortoise / tortoise/tortoise-orm

PydanticMeta max_recursion not being respected

Open
#715 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
5.6k
Forks
516
Avg merge
2d 21h
Merged PRs (30d)
9

Description

Describe the bug
It might be a misunderstanding on my part, but I feel that if I set a max_rercurrsion = 1. It should only contain its direct linked Models:

For instance, consider the following example:

from tortoise.contrib.pydantic.creator import pydantic_model_creator
from tortoise import Tortoise, fields
from tortoise.models import Model


class Tournament(Model):
    id = fields.IntField(pk=True)
    events: fields.ReverseRelation["Event"]


class Event(Model):
    id = fields.IntField(pk=True)
    tournament: fields.ForeignKeyNullableRelation[Tournament] = fields.ForeignKeyField(
        "models.Tournament", related_name="events", null=True
    )


class Address(Model):
    city = fields.CharField(max_length=64)

    event: fields.OneToOneRelation[Event] = fields.OneToOneField(
        "models.Event", on_delete=fields.CASCADE, related_name="address", pk=True
    )

    class PydanticMeta:
        max_recursion = 1


Tortoise.init_models(["__main__"], "models")

Address_Pydantic = pydantic_model_creator(Address)
print(Event_Pydantic.schema_json(indent=4))

I would expect that the Address_Pydantic schema only contains Events data but no Tournament data.
But this is what I get instead:

{
    "title": "Address",
    "type": "object",
    "properties": {
        "city": {
            "title": "City",
            "maxLength": 64,
            "type": "string"
        },
        "event": {
            "title": "Event",
            "allOf": [
                {
                    "$ref": "#/definitions/__main__.Event.hnfky6"
                }
            ]
        },
        "event_id": {
            "title": "Event Id",
            "minimum": 1,
            "maximum": 2147483647,
            "type": "integer"
        }
    },
    "required": [
        "city",
        "event",
        "event_id"
    ],
    "additionalProperties": false,
    "definitions": {
        "__main__.Tournament.leaf": {
            "title": "Tournament",
            "type": "object",
            "properties": {
                "id": {
                    "title": "Id",
                    "minimum": 1,
                    "maximum": 2147483647,
                    "type": "integer"
                }
            },
            "required": [
                "id"
            ],
            "additionalProperties": false
        },
        "__main__.Event.hnfky6": {
            "title": "Event",
            "type": "object",
            "properties": {
                "id": {
                    "title": "Id",
                    "minimum": 1,
                    "maximum": 2147483647,
                    "type": "integer"
                },
                "tournament": {
                    "title": "Tournament",
                    "nullable": true,
                    "allOf": [
                        {
                            "$ref": "#/definitions/__main__.Tournament.leaf"
                        }
                    ]
                }
            },
            "required": [
                "id"
            ],
            "additionalProperties": false
        }
    }
}

I would expect something along the lines of

{
    "title": "Address",
    "type": "object",
    "properties": {
        "city": {
            "title": "City",
            "maxLength": 64,
            "type": "string"
        },
        "event": {
            "title": "Event",
            "allOf": [
                {
                    "$ref": "#/definitions/__main__.Event.hnfky6"
                }
            ]
        },
        "event_id": {
            "title": "Event Id",
            "minimum": 1,
            "maximum": 2147483647,
            "type": "integer"
        }
    },
    "required": [
        "city",
        "event",
        "event_id"
    ],
    "additionalProperties": false,
    "definitions": {
        "__main__.Event.hnfky6": {
            "title": "Event",
            "type": "object",
            "properties": {
                "id": {
                    "title": "Id",
                    "minimum": 1,
                    "maximum": 2147483647,
                    "type": "integer"
                }
            },
            "required": [
                "id"
            ],
            "additionalProperties": false
        }
    }
}

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Run the provided model setup and inspect pydantic_model_creator in tortoise.contrib.pydantic.creator, focusing on how PydanticMeta.max_recursion is applied across related models. Done means the generated Address schema includes Event but does not include Tournament data when max_recursion is 1.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
database
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.