Max nested depth#

As we saw in the previous section, even though we didn’t explicitly exclude the children from the nested Person.children representations, they were not included in the response.

Here’s a reminder of the output:

../../_images/nested_collection_exclude.png

Given that we didn’t explicitly exclude it from the response, each of the Person objects in the children collection should have an empty children collection. The reason they do not is due to max_nested_depth and its default value of 1.

The max_nested_depth attribute is used to limit the depth of nested objects that are included in the response. In this case, the Person object has a children collection, which is a collection of nested Person objects, so this represents a nested depth of 1. The children collections of the items in the Person.children collection are at a 2nd level of nesting, and so are excluded due to the default value of max_nested_depth.

Let’s now modify our script to include the children of children in the response:

 1from __future__ import annotations
 2
 3from dataclasses import dataclass
 4from typing import List
 5
 6from litestar import Litestar, get
 7from litestar.dto import DataclassDTO, DTOConfig
 8
 9
10@dataclass
11class Address:
12    street: str
13    city: str
14    country: str
15
16
17@dataclass
18class Person:
19    name: str
20    age: int
21    email: str
22    address: Address
23    children: List[Person]
24
25
26class ReadDTO(DataclassDTO[Person]):
27    config = DTOConfig(
28        exclude={"email", "address.street", "children.0.email", "children.0.address"},
29        max_nested_depth=2,
30    )
31
32
33@get("/person/{name:str}", return_dto=ReadDTO, sync_to_thread=False)
34def get_person(name: str) -> Person:
35    # Your logic to retrieve the person goes here
36    # For demonstration purposes, a placeholder Person instance is returned
37    address = Address(street="123 Main St", city="Cityville", country="Countryland")
38    child1 = Person(name="Child1", age=10, email="child1@example.com", address=address, children=[])
39    child2 = Person(name="Child2", age=8, email="child2@example.com", address=address, children=[])
40    return Person(
41        name=name,
42        age=30,
43        email=f"email_of_{name}@example.com",
44        address=address,
45        children=[child1, child2],
46    )
47
48
49app = Litestar(route_handlers=[get_person])
 1from __future__ import annotations
 2
 3from dataclasses import dataclass
 4
 5from litestar import Litestar, get
 6from litestar.dto import DataclassDTO, DTOConfig
 7
 8
 9@dataclass
10class Address:
11    street: str
12    city: str
13    country: str
14
15
16@dataclass
17class Person:
18    name: str
19    age: int
20    email: str
21    address: Address
22    children: list[Person]
23
24
25class ReadDTO(DataclassDTO[Person]):
26    config = DTOConfig(
27        exclude={"email", "address.street", "children.0.email", "children.0.address"},
28        max_nested_depth=2,
29    )
30
31
32@get("/person/{name:str}", return_dto=ReadDTO, sync_to_thread=False)
33def get_person(name: str) -> Person:
34    # Your logic to retrieve the person goes here
35    # For demonstration purposes, a placeholder Person instance is returned
36    address = Address(street="123 Main St", city="Cityville", country="Countryland")
37    child1 = Person(name="Child1", age=10, email="child1@example.com", address=address, children=[])
38    child2 = Person(name="Child2", age=8, email="child2@example.com", address=address, children=[])
39    return Person(
40        name=name,
41        age=30,
42        email=f"email_of_{name}@example.com",
43        address=address,
44        children=[child1, child2],
45    )
46
47
48app = Litestar(route_handlers=[get_person])

We now see those empty collections in our output:

../../_images/max_nested_depth.png

Now that we’ve seen how to use the max_nested_depth configuration, we’ll revert to using the default value of 1 for the remainder of this tutorial.