Skip to main content

Pydantic change detection

PyPI Downloads PyPI Downloads

Installation

Just use pip install pydantic-changedetect to install the library.

Note: pydantic-changedetect is compatible with pydantic version 2.x on Python 3.10, 3.11, 3.12, 3.13 and 3.14. This is also ensured running all tests on all those versions using tox.

About

When working with database models it is pretty common to want to detect changes to the model attributes. The ChangeDetectionMixin just provides this mechanism to any pydantic models. Changes will be detected and stored after the model was constructed.

Using the ChangeDetectionMixin the pydantic models are extended, so:

  • obj.model_changed_fields contains a list of all changed fields
    • obj.model_self_changed_fields contains a list of all changed fields for the current object, ignoring all nested models.
    • obj.model_changed_fields_recursive contains a list of all changed fields and also include the named of the fields changed in nested models using a dotted field name syntax (like nested.field).
  • obj.model_original will include the original values of all changed fields in a dict.
  • obj.model_has_changed returns True if any field has changed.
  • obj.model_set_changed() manually sets fields as changed.
    • obj.model_set_changed("field_a", "field_b") will set multiple fields as changed.
    • obj.model_set_changed("field_a", original="old") will set a single field as changed and also store its original value.
  • obj.model_reset_changed() resets all changed fields.
  • obj.model_dump() and obj.model_dump_json() accept an additional parameter exclude_unchanged, which - when set to True - will only export the changed fields.
    Note: When using pydantic 1.x you need to use obj.dict() and obj.json(). Both also accept exclude_unchanged.
  • obj.model_restore_original() will create a new instance of the model containing its original state.
  • obj.model_get_original_field_value("field_name") will return the original value for just one field. It will call model_restore_original() on the current field value if the field is set to a ChangeDetectionMixin instance (or list/dict of those).
  • obj.model_mark_changed("marker_name") and obj.model_unmark_changed("marker_name") allow to add arbitrary change markers. An instance with a marker will be seen as changed (obj.model_has_changed == True). Markers are stored in obj.model_changed_markers as a set.

Example

import pydantic
from pydantic_changedetect import ChangeDetectionMixin

class Something(ChangeDetectionMixin, pydantic.BaseModel):
    name: str


something = Something(name="something")
something.model_has_changed  # = False
something.model_changed_fields  # = set()
something.name = "something else"
something.model_has_changed  # = True
something.model_changed_fields  # = {"name"}

original = something.model_restore_original()
original.name  # = "something"
original.model_has_changed  # = False

When will a change be detected

pydantic-changedetect will see changes when an attribute value is changes using an attribute assignment like something.name = "something else" in the example above. Such an assignment will be seen as a change unless the new value is the same and the type of the value is None or of type str, int, float, bool or decimal.Decimal.

Restrictions

ChangeDetectionMixin currently cannot detect changes inside lists, dicts and other structured objects. In those cases you are required to set the changed state yourself using model_set_changed(). It is recommended to pass the original value to model_set_changed() when you want to also keep track of the actual changes compared to the original value. Be advised to .copy() the original value as lists/dicts will always be changed in place.

import pydantic
from pydantic_changedetect import ChangeDetectionMixin

class TodoList(ChangeDetectionMixin, pydantic.BaseModel):
    items: list[str]


todos = TodoList(items=["release new version"])
original_items = todos.items.copy()
todos.items.append("create better docs")  # This change will NOT be seen yet
todos.model_has_changed  # = False
todos.model_set_changed("items", original=original_items)  # Mark field as changed and store original value
todos.model_has_changed  # = True

Changed markers

You may also just mark the model as changed. This can be done using changed markers. A change marker is just a string that is added as the marker, models with such an marker will also be seen as changed. Changed markers also allow to mark models as changed when related data was changed - for example to also update a parent object in the database when some children were changed.

import pydantic
from pydantic_changedetect import ChangeDetectionMixin

class Something(ChangeDetectionMixin, pydantic.BaseModel):
  name: str


something = Something(name="something")
something.model_has_changed  # = False
something.model_mark_changed("mood")
something.model_has_changed  # = True
something.model_changed_markers  # {"mood"}
something.model_unmark_changed("mood")  # also will be reset on something.model_reset_changed()
something.model_has_changed  # = False

Contributing

If you want to contribute to this project, feel free to just fork the project, create a dev branch in your fork and then create a pull request (PR). If you are unsure about whether your changes really suit the project please create an issue first, to talk about this.

Metadata

Release files for pydantic-changedetect 0.11.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pydantic-changedetect 0.11.1
File Size Uploaded Provenance
pydantic_changedetect-0.11.1.tar.gz 10.0 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for pydantic-changedetect 0.11.1
File Interpreter ABI Platform
pydantic_changedetect-0.11.1-py3-none-any.whl Python 3 none any Details

Total release size: 21.6 kB

Release files / pydantic_changedetect-0.11.1.tar.gz

Download URL pydantic_changedetect-0.11.1.tar.gz
Size 10.0 kB
Tags Source
SHA-256 checksum
How to use checksums
decb63efec75fda5bb044fff7760f9951334cab7fd14d86f0c1d62b119a5bfda
BLAKE2b-256 checksum
How to use checksums
45cf0cfb1358808723846f4718be76c72298321f220e8c593df6f0420e31388a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.11.24 {"installer":{"name":"uv","version":"0.11.24","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}

Release files / pydantic_changedetect-0.11.1-py3-none-any.whl

Download URL pydantic_changedetect-0.11.1-py3-none-any.whl
Size 11.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
041dbe774b51b04fe2c41b69749922696417340689afe6a8677ba0c4630b910c
BLAKE2b-256 checksum
How to use checksums
cb2cf3b0746bb81c04192c30d3cc3dbd1907484915a956178c0cecb86bdd21e8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.11.24 {"installer":{"name":"uv","version":"0.11.24","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}

Security for pydantic-changedetect 0.11.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page