Skip to main content

Views for Pydantic models

Project description

Documentation Status PyPI - Python Version PyPI - Types PyPI - License PyPI - Version

Typed views for Pydantic models

pydantic-views lets you derive focused, type-safe Pydantic models (“views”) from a base model. Each view exposes only the fields appropriate for a given operation—create, update, load, or a custom flow—so you avoid hand-maintaining parallel schemas.

Typical service signatures become easy to express:

ExampleModelCreate = BuilderCreate().build_view(ExampleModel)
ExampleModelCreateResult = BuilderCreateResult().build_view(ExampleModel)
ExampleModelLoad = BuilderLoad().build_view(ExampleModel)
ExampleModelUpdate = BuilderUpdate().build_view(ExampleModel)

def create(input: ExampleModelCreate) -> ExampleModelCreateResult: ...
def load(model_id: str) -> ExampleModelLoad: ...
def update(model_id: str, input: ExampleModelUpdate) -> ExampleModelLoad: ...

Features

  • Unlimited views per model (create, update, load, custom).

  • Works on nested models; referenced models get views too.

  • Builders for common patterns, or define views manually.

  • Fully typed with shipped py.typed and tests.

  • Open source and published on PyPI.

Installation

Using pip:

pip install pydantic-views

Using poetry:

poetry add pydantic-views

Using uv:

uv add pydantic-views

Quickstart

Mark each field with its access mode using the provided annotations. Unmarked fields default to read/write.

from typing import Annotated

from pydantic import BaseModel, computed_field, gt
from pydantic_views import AccessMode, Hidden, ReadOnly, ReadOnlyOnCreation

class ExampleModel(BaseModel):
    # Unmarked fields are read/write everywhere.
    field_str: str

    # Read-only fields are removed from create and update views.
    field_read_only_str: ReadOnly[str]

    # Read-only-on-creation fields are hidden on create, update and load views,
    # but appear on create-result views.
    field_api_secret: ReadOnlyOnCreation[str]

    # Combine access modes with Annotated and keep validators (gt in this case).
    field_int: Annotated[int, AccessMode.READ_ONLY, AccessMode.WRITE_ONLY_ON_CREATION, gt(5)]

    # Hidden fields never appear.
    field_hidden_int: Hidden[int]

    # Computed fields appear only on read views.
    @computed_field
    def field_computed_field(self) -> int:
        return self.field_hidden_int * 5

Build a load view:

from pydantic_views import BuilderLoad

ExampleModelLoad = BuilderLoad().build_view(ExampleModel)

Which is equivalent to:

from pydantic import gt
from pydantic_views import View

class ExampleModelLoad(View[ExampleModel]):
    field_str: str
    field_int: Annotated[int, gt(5)]
    field_computed_field: int

To build an update view:

from pydantic_views import BuilderUpdate

ExampleModelUpdate = BuilderUpdate().build_view(ExampleModel)

Which is equivalent to:

from pydantic import Field, PydanticUndefined
from pydantic_views import View

class ExampleModelUpdate(View[ExampleModel]):
    field_str: str = Field(default_factory=lambda: PydanticUndefined)

On Update views every field uses a default factory that returns PydanticUndefined, so fields become optional. Applying the view to a model only updates values that were set.

original_model = ExampleModel(
    field_str="anything"
    field_read_only_str="anything"
    field_api_secret="anything"
    field_int=10
    field_hidden_int=33
)

update = ExampleModelUpdate(field_str="new_data")

updated_model = update.view_apply_to(original_model)

assert isinstance(updated_model, ExampleModel)
assert updated_model.field_str == "new_data"

If a field is not set on the update view, the original value is kept.

original_model = ExampleModel(
    field_str="anything"
    field_read_only_str="anything"
    field_api_secret="anything"
    field_int=10
    field_hidden_int=33
)

update = ExampleModelUpdate()

updated_model = update.view_apply_to(original_model)

assert isinstance(updated_model, ExampleModel)
assert updated_model.field_str == "anything"

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pydantic_views-0.3.0rc0.tar.gz (8.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pydantic_views-0.3.0rc0-py3-none-any.whl (9.8 kB view details)

Uploaded Python 3

File details

Details for the file pydantic_views-0.3.0rc0.tar.gz.

File metadata

  • Download URL: pydantic_views-0.3.0rc0.tar.gz
  • Upload date:
  • Size: 8.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.26 {"installer":{"name":"uv","version":"0.9.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for pydantic_views-0.3.0rc0.tar.gz
Algorithm Hash digest
SHA256 3d9c9a728aef4f859b86b37a7919ea56a52ebb4d0b38750126ab1a30f409eff2
MD5 24fedc94b388c27670c365030fde3acd
BLAKE2b-256 b02414ac7c38d81fae186ef2769d361dd5a2e19c7518fc38374c605a6ada48b4

See more details on using hashes here.

File details

Details for the file pydantic_views-0.3.0rc0-py3-none-any.whl.

File metadata

  • Download URL: pydantic_views-0.3.0rc0-py3-none-any.whl
  • Upload date:
  • Size: 9.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.26 {"installer":{"name":"uv","version":"0.9.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for pydantic_views-0.3.0rc0-py3-none-any.whl
Algorithm Hash digest
SHA256 b5f2d3c1968e80115e8035f212fdf3dbd339fa710b8a811895e7da19af6e6d12
MD5 78073987affc27c8322151696eec128b
BLAKE2b-256 749250a2c251da9750853774d69097fc4dfbccd134b60a2df9e170cbf48c3320

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page