Maxim Suslov
Maxim Suslov

Reputation: 5485

pydantic: exclude computed field from dump

In pydantic v2, the following code:

from __future__ import annotations
import pydantic
from pprint import pprint


class System(pydantic.BaseModel):
    id: int
    name: str
    subsystems: list[System] | None = None

    @pydantic.computed_field()
    @property
    def computed(self) -> str:
        return self.name.upper()


systems = System(
    id=1,
    name="Main system",
    subsystems=[
        System(id=2, name="Subsystem A"),
        System(id=3, name="Subsystem B"),
    ],
)
pprint(systems.model_dump(), indent=2)

prints:

{ 'computed': 'MAIN SYSTEM',
  'id': 1,
  'name': 'Main system',
  'subsystems': [ { 'computed': 'SUBSYSTEM A',
                    'id': 2,
                    'name': 'Subsystem A',
                    'subsystems': None},
                  { 'computed': 'SUBSYSTEM B',
                    'id': 3,
                    'name': 'Subsystem B',
                    'subsystems': None}]}

I want to exclude the computed field computed.

pprint(systems.model_dump(exclude={'computed': True}), indent=2)

prints only root element without computed:

{ 'id': 1,
  'name': 'Main system',
  'subsystems': [ { 'computed': 'SUBSYSTEM A',
                    'id': 2,
                    'name': 'Subsystem A',
                    'subsystems': None},
                  { 'computed': 'SUBSYSTEM B',
                    'id': 3,
                    'name': 'Subsystem B',
                    'subsystems': None}]}

How to exclude computed field (e.g. computed) from dump?

I want to serialize via .model_dump() because:

Upvotes: 3

Views: 2316

Answers (2)

Maxim Suslov
Maxim Suslov

Reputation: 5485

According to the documentation on computed_field:

computed_field

Decorator to include property and cached_property when serializing models or dataclasses.

This is useful for fields that are computed from other fields, or for fields that are expensive to compute and should be cached.

In other words, if don't want to include (= exclude) a field we shouldn't use computed_field decorator:

from __future__ import annotations
import pydantic
from pprint import pprint

class System(pydantic.BaseModel):
    id: int
    name: str
    subsystems: list[System] | None = None

    # comment or remove it
    # @pydantic.computed_field()
    @property
    def computed(self) -> str:
        return self.name.upper()


systems = System(
    id=1,
    name="Main system",
    subsystems=[
        System(id=2, name="Subsystem A"),
        System(id=3, name="Subsystem B"),
    ],
)
pprint(systems.model_dump(), indent=2)
print(systems.computed)  # but it is still there

Output is:

{ 'id': 1,
  'name': 'Main system',
  'subsystems': [ {'id': 2, 'name': 'Subsystem A', 'subsystems': None},
                  {'id': 3, 'name': 'Subsystem B', 'subsystems': None}]}
MAIN SYSTEM

Upvotes: 2

TanThien
TanThien

Reputation: 752

You can create a function to serialize what you want. Here, I use a function to return dict and exclude computed

from __future__ import annotations
import pydantic
from pprint import pprint


class System(pydantic.BaseModel):
    id: int
    name: str
    subsystems: list[System] | None = None

    @pydantic.computed_field()
    @property
    def computed(self) -> str:
        return self.name.upper()

    def as_dict(self):
        return {
            "id": self.id,
            "name": self.name,
            "subsystems": [i.model_dump(exclude={'computed'}) for i in self.subsystems]
        }


systems = System(
    id=1,
    name="Main system",
    subsystems=[
        System(id=2, name="Subsystem A"),
        System(id=3, name="Subsystem B"),
    ],
)
pprint(systems.as_dict(), indent=2)

Upvotes: -1

Related Questions