Accessing the data#

Sometimes, it doesn’t make sense for data to be immediately parsed into an instance of the target class. We just saw an example of this in the previous section, Read only fields. When required fields are excluded from, or do not exist in the client submitted data we will get an error upon instantiation of the class.

The solution to this is the DTOData type.

 1from __future__ import annotations
 2
 3from dataclasses import dataclass
 4
 5from litestar import Litestar, post
 6from litestar.dto import DataclassDTO, DTOConfig, DTOData
 7
 8
 9@dataclass
10class Person:
11    name: str
12    age: int
13    email: str
14    id: int
15
16
17class ReadDTO(DataclassDTO[Person]):
18    config = DTOConfig(exclude={"email"})
19
20
21class WriteDTO(DataclassDTO[Person]):
22    config = DTOConfig(exclude={"id"})
23
24
25@post("/person", dto=WriteDTO, return_dto=ReadDTO, sync_to_thread=False)
26def create_person(data: DTOData[Person]) -> Person:
27    # Logic for persisting the person goes here
28    return data.create_instance(id=1)
29
30
31app = Litestar(route_handlers=[create_person])

The DTOData type is a container for data that can be used to create instances, and access the underlying parsed and validated data. In our latest adjustments, we import that from litestar.dto.factory.

The handler function’s data parameter type is changed to DTOData[Person] instead of Person, and accordingly, the value injected to represent the inbound client data will be an instance of DTOData.

In the handler, we produce a value for the id field, and create an instance of Person using the create_instance method of the DTOData instance.

And our app is back to a working state:

../../_images/dto_data.png

Tip

To provide values for nested attributes you can use the “double-underscore” syntax as a keyword argument to the create_instance() method. For example, address__id=1 will set the id attribute of the address attribute of the created instance.

See Providing values for nested data for more information.

The DTOData type has some other useful methods, and we’ll take a look at those in the next section: Updating instances.