# pydantic-strict-partial
[](https://badge.fury.io/py/pydantic-strict-partial)
[](https://pypi.python.org/pypi/pydantic-strict-partial/)
[](https://github.com/ADR-007/pydantic-strict-partial/actions/workflows/ci.yaml)

## About
Create partial models based on the original Pydantic models.
This makes all the fields optional.
This **doesn't** make them nullable and **doesn't** disable validation.
The only thing it does is provide default values for those fields (`None` by default),
so you can use `model.model_dump(exclude_unset=True)` command to receive specified values only.
The most common use case is a `PATCH` request on **FastAPI** endpoints where you want to allow partial updates.
## Installation
`pydantic-strict-partial` compatible with Python 3.10+ and Pydantic 2.1+.
### Using pip
```bash
pip install pydantic-strict-partial
```
### Using poetry
```bash
poetry add pydantic-strict-partial
```
## Usage
```python
from typing import Annotated
from annotated_types import Ge
from pydantic import BaseModel
from pydantic_strict_partial import create_partial_model
class UserSchema(BaseModel):
name: str
nickname: str | None
age: Annotated[int, Ge(18)]
UserPartialUpdateSchema = create_partial_model(UserSchema)
assert UserPartialUpdateSchema(age=20).model_dump(exclude_unset=True) == {
'age': 20
}
UserPartialUpdateSchema(name=None) # raises ValidationError
UserPartialUpdateSchema(age=17) # raises ValidationError
```
There is also possible to specify a limited list of fields to be partial:
```python
UserPartialUpdateSchema = create_partial_model(UserSchema, 'name', 'nickname')
```
Or to make all fields partial except for the specified ones:
```python
UserPartialCreateSchema = create_partial_model(UserSchema, required_fields=['age'])
```
## Known limitations
#### MyPy: "is not valid as a type" error
You may be faced with `Variable "UserPartialUpdateSchema" is not valid as a type` error.
There is no good solution for that. But the next approach can be used as a workaround:
```py
class UserPartialUpdateSchema(create_partial_model(UserSchema)): # type: ignore[misc]
pass
```
## Alternatives
[pydantic-partial](https://github.com/team23/pydantic-partial) - it makes all fields nullable and disables all validators, which is not suitable for payload validation on `PATCH` endpoints.
Raw data
{
"_id": null,
"home_page": "https://github.com/ADR-007/pydantic-strict-partial",
"name": "pydantic-strict-partial",
"maintainer": null,
"docs_url": null,
"requires_python": "<4.0,>=3.10",
"maintainer_email": null,
"keywords": "pydantic, partial, fastapi",
"author": "Adrian Dankiv",
"author_email": "adr-007@ukr.net",
"download_url": "https://files.pythonhosted.org/packages/bd/a6/7d5a0116e7d517f57242b0dd90272ce154713c4a5772d069059eccbf715f/pydantic_strict_partial-0.6.2.tar.gz",
"platform": null,
"description": "# pydantic-strict-partial\n\n[](https://badge.fury.io/py/pydantic-strict-partial)\n[](https://pypi.python.org/pypi/pydantic-strict-partial/)\n[](https://github.com/ADR-007/pydantic-strict-partial/actions/workflows/ci.yaml)\n\n\n## About\n\nCreate partial models based on the original Pydantic models. \n\nThis makes all the fields optional. \nThis **doesn't** make them nullable and **doesn't** disable validation.\nThe only thing it does is provide default values for those fields (`None` by default), \nso you can use `model.model_dump(exclude_unset=True)` command to receive specified values only.\n\nThe most common use case is a `PATCH` request on **FastAPI** endpoints where you want to allow partial updates.\n\n## Installation\n\n`pydantic-strict-partial` compatible with Python 3.10+ and Pydantic 2.1+.\n\n### Using pip\n```bash\npip install pydantic-strict-partial\n```\n\n### Using poetry\n```bash\npoetry add pydantic-strict-partial\n```\n\n## Usage\n\n```python\nfrom typing import Annotated\n\nfrom annotated_types import Ge\nfrom pydantic import BaseModel\n\nfrom pydantic_strict_partial import create_partial_model\n\n\nclass UserSchema(BaseModel):\n name: str\n nickname: str | None\n age: Annotated[int, Ge(18)]\n\n\nUserPartialUpdateSchema = create_partial_model(UserSchema)\n\nassert UserPartialUpdateSchema(age=20).model_dump(exclude_unset=True) == {\n 'age': 20\n}\n\nUserPartialUpdateSchema(name=None) # raises ValidationError\nUserPartialUpdateSchema(age=17) # raises ValidationError\n\n```\n\nThere is also possible to specify a limited list of fields to be partial:\n\n```python\nUserPartialUpdateSchema = create_partial_model(UserSchema, 'name', 'nickname')\n```\n\nOr to make all fields partial except for the specified ones:\n\n```python\nUserPartialCreateSchema = create_partial_model(UserSchema, required_fields=['age'])\n```\n\n## Known limitations\n\n#### MyPy: \"is not valid as a type\" error\n\nYou may be faced with `Variable \"UserPartialUpdateSchema\" is not valid as a type` error.\nThere is no good solution for that. But the next approach can be used as a workaround: \n\n```py\nclass UserPartialUpdateSchema(create_partial_model(UserSchema)): # type: ignore[misc]\n pass\n```\n\n## Alternatives\n\n[pydantic-partial](https://github.com/team23/pydantic-partial) - it makes all fields nullable and disables all validators, which is not suitable for payload validation on `PATCH` endpoints.\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Makes partial Pydantic models without making fields nullable.",
"version": "0.6.2",
"project_urls": {
"Homepage": "https://github.com/ADR-007/pydantic-strict-partial"
},
"split_keywords": [
"pydantic",
" partial",
" fastapi"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "e5a75b40a0f327193c4cfebbc2b26df7b1b02304fca40da23825ca231a11efe9",
"md5": "8f90764310e744afd564f3a0fa49f562",
"sha256": "acb1f020eec6d892dc104184a0cc3d471622d7025216e2eb9f4b9e5ce78acebc"
},
"downloads": -1,
"filename": "pydantic_strict_partial-0.6.2-py3-none-any.whl",
"has_sig": false,
"md5_digest": "8f90764310e744afd564f3a0fa49f562",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0,>=3.10",
"size": 4108,
"upload_time": "2025-01-22T13:16:48",
"upload_time_iso_8601": "2025-01-22T13:16:48.465557Z",
"url": "https://files.pythonhosted.org/packages/e5/a7/5b40a0f327193c4cfebbc2b26df7b1b02304fca40da23825ca231a11efe9/pydantic_strict_partial-0.6.2-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "bda67d5a0116e7d517f57242b0dd90272ce154713c4a5772d069059eccbf715f",
"md5": "6c9ac0a0fe0b8c357ccabcb54f0811a1",
"sha256": "d5827fccfa30c63f8a7c7303079f245bbb7af7eed6eb53a0854264072007083c"
},
"downloads": -1,
"filename": "pydantic_strict_partial-0.6.2.tar.gz",
"has_sig": false,
"md5_digest": "6c9ac0a0fe0b8c357ccabcb54f0811a1",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4.0,>=3.10",
"size": 4822,
"upload_time": "2025-01-22T13:16:49",
"upload_time_iso_8601": "2025-01-22T13:16:49.982563Z",
"url": "https://files.pythonhosted.org/packages/bd/a6/7d5a0116e7d517f57242b0dd90272ce154713c4a5772d069059eccbf715f/pydantic_strict_partial-0.6.2.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-01-22 13:16:49",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "ADR-007",
"github_project": "pydantic-strict-partial",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "pydantic-strict-partial"
}