# Pydantic Partials

An easy way to add or create partials for Pydantic models.

![PythonSupport](https://img.shields.io/static/v1?label=python&message=%203.10|%203.11|%203.12&color=blue?style=flat-square&logo=python)
![PyPI version](https://badge.fury.io/py/xmodel.svg?)

## Documentation

**[📄 Detailed Documentation](https://joshorr.github.io/pydantic-partials/latest/)** | **[🐍 PyPi](https://pypi.org/project/pydantic-partials/)**

## Quick Start

```shell
poetry install pydantic-partials
```

or

```shell
pip install pydantic-partials
```

By default, all fields without a default value will have the ability to be partial,
and can be missing from both validation and serialization.

Very basic example is below:

```python
from pydantic_partials import PartialModel, Missing, Partial


class MyModel(PartialModel):
    some_attr: str
    another_field: str

# By default, Partial fields without any value will get set to a special `Missing` type.
# Any field that is set to Missing is excluded from the model_dump/model_dump_json
obj = MyModel()
assert obj.some_attr is Missing
assert obj.model_dump() == {}

# You can set the real value at any time, and it will behave like expected.
obj.some_attr = 'hello'
assert obj.some_attr is 'hello'
assert obj.model_dump() == {'some_attr': 'hello'}

# You can always manually set a field to `Missing` directly.
obj.some_attr = Missing

# And now it's removed from the model-dump.
assert obj.model_dump() == {}

# The json dump is also affected in the same way.
assert obj.model_dump_json() == '{}'

# Any non-missing fields will be included when dumping/serializing model.
obj.another_field = 'assigned-value'

# And now it's removed from the model-dump.
assert obj.model_dump() == {'another_field': 'assigned-value'}
```


You can turn off this default behavior by via `auto_partials` class argument or modeL_config option:

```python
from pydantic_partials import PartialModel, PartialConfigDict

class TestModel1(PartialModel, auto_partials=False):
    ...

class TestModel2(PartialModel):
    model_config = PartialConfigDict(auto_partials=False)
    ...

```

You can disable this automatic function. This means you have complete control of exactly which field 
can be partial or not.  You can use either the generic `Partial[...]` generic or a union with `MissingType`
to mark a field as a partial field.  The generic simple makes the union to MissingType for you.

Example of disabling auto_partials:

```python
from pydantic_partials import PartialModel, Missing, MissingType, Partial, PartialConfigDict
from decimal import Decimal
from pydantic import ValidationError

class TestModel(PartialModel, auto_partials=False):
    # Can use `Partial` generic type
    partial_int: Partial[int] = Missing
    
    # Or union with `MissingType`
    partial_str: str | MissingType
    
    required_decimal: Decimal
    
try:
    TestModel()
except ValidationError as e:
    print(f'Pydantic will state `required_decimal` is required: {e}')
else:
    raise Exception('Pydantic should have required `required_decimal`.')
    
obj = TestModel(required_decimal='1.34')

# You can find out at any time if a field is missing or not:
assert obj.partial_int is Missing
assert obj.partial_str is Missing

assert obj.required_decimal == Decimal('1.34')

```



