Excluding from collections of nested models#
In Python, generic types can accept one or more type parameters (types that are enclosed in square brackets). This
pattern is often seen when representing a collection of some type, such as List[Person], where List is a
generic container type, and Person specializes the contents of the collection to contain only instances of the
Person class.
Given a generic type, with an arbitrary number of type parameters (e.g., GenericType[Type0, Type1, ..., TypeN]),
we use the index of the type parameter to indicate which type the exclusion should refer to. For example, a.0.b,
excludes the b field from the first type parameter of a, a.1.b excludes the b field from the second type
parameter of a, and so on.
To demonstrate, lets add a self-referencing children relationship to our Person model:
1from __future__ import annotations
2
3from dataclasses import dataclass
4
5from litestar import Litestar, get
6from litestar.dto import DataclassDTO, DTOConfig
7from litestar.params import FromPath
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(exclude={"email", "address.street", "children.0.email", "children.0.address"})
28
29
30@get("/person/{name:str}", return_dto=ReadDTO, sync_to_thread=False)
31def get_person(name: FromPath[str]) -> Person:
32 # Your logic to retrieve the person goes here
33 # For demonstration purposes, a placeholder Person instance is returned
34 address = Address(street="123 Main St", city="Cityville", country="Countryland")
35 child1 = Person(name="Child1", age=10, email="child1@example.com", address=address, children=[])
36 child2 = Person(name="Child2", age=8, email="child2@example.com", address=address, children=[])
37 return Person(
38 name=name,
39 age=30,
40 email=f"email_of_{name}@example.com",
41 address=address,
42 children=[child1, child2],
43 )
44
45
46app = Litestar(route_handlers=[get_person])
Now, a Person can have one or many children, and each child can have one or many children, and so on.
We have explicitly excluded the email and address fields of all represented children
("children.0.email", "children.0.address").
In our handler we add children to the Person, and each child has no children of their own.
Here’s the output:
Fantastic! Our children are now represented in the output, and their emails and addresses are excluded. However,
astute readers may have noticed that we didn’t exclude the children field of Person.children
(e.g., children.0.children), yet that field is not represented in the output. To understand why, we’ll next look at
the max_nested_depth configuration option.