Name | pydantic-view JSON |
Version |
2.0.1
JSON |
| download |
home_page | None |
Summary | View decorator to create the child pydantic models from the root model. |
upload_time | 2024-10-14 14:34:39 |
maintainer | None |
docs_url | None |
author | Roman Koshel |
requires_python | <4.0,>=3.8 |
license | MIT |
keywords |
pydantic
model
view
utils
|
VCS |
|
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
# Pydantic view helper decorator
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
### Installation
```bash
pip install pydantic_view
```
### Usage
```python
In [1]: from pydantic import BaseModel, Field
...: from pydantic_view import view
...:
...:
...: class User(BaseModel):
...: id: int
...: username: str
...: password: str
...: address: str
...:
...: @view("Create", exclude={"id"})
...: class UserCreate(User):
...: pass
...:
...: @view("Update")
...: class UserUpdate(User):
...: pass
...:
...: @view("Patch")
...: class UserPatch(User):
...: username: str = None
...: password: str = None
...: address: str = None
...:
...: @view("Out", exclude={"password"})
...: class UserOut(User):
...: pass
In [2]: user = User(id=0, username="human", password="iamaman", address="Earth")
...: user.Out()
...:
Out[2]: UserOut(id=0, username='human', address='Earth')
In [3]: User.Update(id=0, username="human", password="iamasuperman", address="Earth")
...:
Out[3]: UserUpdate(id=0, username='human', password='iamasuperman', address='Earth')
In [4]: User.Patch(id=0, address="Mars")
...:
Out[4]: UserPatch(id=0, username=None, password=None, address='Mars')
```
### FastAPI example
```python
from typing import Optional
from fastapi import FastAPI
from fastapi.testclient import TestClient
from pydantic import BaseModel, ConfigDict, Field
from pydantic_view import view, view_field_validator
class UserSettings(BaseModel):
model_config = ConfigDict(extra="forbid")
public: Optional[str] = None
secret: Optional[str] = None
@view("Out", exclude={"secret"})
class UserSettingsOut(UserSettings):
pass
@view("Create")
class UserSettingsCreate(UserSettings):
pass
@view("Update")
class UserSettingsUpdate(UserSettings):
pass
@view("Patch")
class UserSettingsPatch(UserSettings):
public: str = None
secret: str = None
class User(BaseModel):
model_config = ConfigDict(extra="forbid")
id: int
username: str
password: str = Field(default_factory=lambda: "password")
settings: UserSettings
@view_field_validator({"Create", "Update", "Patch"}, "username")
@classmethod
def validate_username(cls, v):
if len(v) < 3:
raise ValueError
return v
@view("Out", exclude={"password"})
class UserOut(User):
pass
@view("Create", exclude={"id"})
class UserCreate(User):
settings: UserSettings = Field(default_factory=UserSettings)
@view("Update", exclude={"id"})
class UserUpdate(User):
pass
@view("Patch", exclude={"id"})
class UserPatch(User):
username: str = None
password: str = None
settings: UserSettings = None
app = FastAPI()
db = {}
@app.get("/users/{user_id}", response_model=User.Out)
async def get(user_id: int) -> User.Out:
return db[user_id]
@app.post("/users", response_model=User.Out)
async def post(user: User.Create) -> User.Out:
user_id = 0 # generate_user_id()
db[0] = User(id=user_id, **user.model_dump())
return db[0]
@app.put("/users/{user_id}", response_model=User.Out)
async def put(user_id: int, user: User.Update) -> User.Out:
db[user_id] = User(id=user_id, **user.model_dump())
return db[user_id]
@app.patch("/users/{user_id}", response_model=User.Out)
async def patch(user_id: int, user: User.Patch) -> User.Out:
db[user_id] = User(**{**db[user_id].model_dump(), **user.model_dump(exclude_unset=True)})
return db[user_id]
def test_fastapi():
client = TestClient(app)
# POST
response = client.post(
"/users",
json={
"username": "admin",
"password": "admin",
},
)
assert response.status_code == 200, response.text
assert response.json() == {
"id": 0,
"username": "admin",
"settings": {"public": None},
}
# GET
response = client.get("/users/0")
assert response.status_code == 200, response.text
assert response.json() == {
"id": 0,
"username": "admin",
"settings": {"public": None},
}
# PUT
response = client.put(
"/users/0",
json={
"username": "superadmin",
"password": "superadmin",
"settings": {"public": "foo", "secret": "secret"},
},
)
assert response.status_code == 200, response.text
assert response.json() == {
"id": 0,
"username": "superadmin",
"settings": {"public": "foo"},
}
# PATCH
response = client.patch(
"/users/0",
json={
"username": "guest",
"settings": {"public": "bar"},
},
)
assert response.status_code == 200, response.text
assert response.json() == {
"id": 0,
"username": "guest",
"settings": {"public": "bar"},
}
```
Raw data
{
"_id": null,
"home_page": null,
"name": "pydantic-view",
"maintainer": null,
"docs_url": null,
"requires_python": "<4.0,>=3.8",
"maintainer_email": null,
"keywords": "pydantic, model, view, utils",
"author": "Roman Koshel",
"author_email": "roma.koshel@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/15/ea/21092800171d05350416222981038dbfcbbb4240c01385b4e2a08b3d8975/pydantic_view-2.0.1.tar.gz",
"platform": null,
"description": "# Pydantic view helper decorator\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\n### Installation\n```bash\npip install pydantic_view\n```\n\n### Usage\n\n```python\nIn [1]: from pydantic import BaseModel, Field\n ...: from pydantic_view import view\n ...: \n ...: \n ...: class User(BaseModel):\n ...: id: int\n ...: username: str\n ...: password: str\n ...: address: str\n ...: \n ...: @view(\"Create\", exclude={\"id\"})\n ...: class UserCreate(User):\n ...: pass\n ...:\n ...: @view(\"Update\")\n ...: class UserUpdate(User):\n ...: pass\n ...:\n ...: @view(\"Patch\")\n ...: class UserPatch(User):\n ...: username: str = None\n ...: password: str = None\n ...: address: str = None\n ...:\n ...: @view(\"Out\", exclude={\"password\"})\n ...: class UserOut(User):\n ...: pass\n\nIn [2]: user = User(id=0, username=\"human\", password=\"iamaman\", address=\"Earth\")\n ...: user.Out()\n ...: \nOut[2]: UserOut(id=0, username='human', address='Earth')\n\nIn [3]: User.Update(id=0, username=\"human\", password=\"iamasuperman\", address=\"Earth\")\n ...: \nOut[3]: UserUpdate(id=0, username='human', password='iamasuperman', address='Earth')\n\nIn [4]: User.Patch(id=0, address=\"Mars\")\n ...: \nOut[4]: UserPatch(id=0, username=None, password=None, address='Mars')\n```\n\n\n### FastAPI example\n\n```python\nfrom typing import Optional\n\nfrom fastapi import FastAPI\nfrom fastapi.testclient import TestClient\nfrom pydantic import BaseModel, ConfigDict, Field\n\nfrom pydantic_view import view, view_field_validator\n\n\nclass UserSettings(BaseModel):\n model_config = ConfigDict(extra=\"forbid\")\n\n public: Optional[str] = None\n secret: Optional[str] = None\n\n\n@view(\"Out\", exclude={\"secret\"})\nclass UserSettingsOut(UserSettings):\n pass\n\n\n@view(\"Create\")\nclass UserSettingsCreate(UserSettings):\n pass\n\n\n@view(\"Update\")\nclass UserSettingsUpdate(UserSettings):\n pass\n\n\n@view(\"Patch\")\nclass UserSettingsPatch(UserSettings):\n public: str = None\n secret: str = None\n\n\nclass User(BaseModel):\n model_config = ConfigDict(extra=\"forbid\")\n\n id: int\n username: str\n password: str = Field(default_factory=lambda: \"password\")\n settings: UserSettings\n\n @view_field_validator({\"Create\", \"Update\", \"Patch\"}, \"username\")\n @classmethod\n def validate_username(cls, v):\n if len(v) < 3:\n raise ValueError\n return v\n\n\n@view(\"Out\", exclude={\"password\"})\nclass UserOut(User):\n pass\n\n\n@view(\"Create\", exclude={\"id\"})\nclass UserCreate(User):\n settings: UserSettings = Field(default_factory=UserSettings)\n\n\n@view(\"Update\", exclude={\"id\"})\nclass UserUpdate(User):\n pass\n\n\n@view(\"Patch\", exclude={\"id\"})\nclass UserPatch(User):\n username: str = None\n password: str = None\n settings: UserSettings = None\n\n\napp = FastAPI()\n\ndb = {}\n\n\n@app.get(\"/users/{user_id}\", response_model=User.Out)\nasync def get(user_id: int) -> User.Out:\n return db[user_id]\n\n\n@app.post(\"/users\", response_model=User.Out)\nasync def post(user: User.Create) -> User.Out:\n user_id = 0 # generate_user_id()\n db[0] = User(id=user_id, **user.model_dump())\n return db[0]\n\n\n@app.put(\"/users/{user_id}\", response_model=User.Out)\nasync def put(user_id: int, user: User.Update) -> User.Out:\n db[user_id] = User(id=user_id, **user.model_dump())\n return db[user_id]\n\n\n@app.patch(\"/users/{user_id}\", response_model=User.Out)\nasync def patch(user_id: int, user: User.Patch) -> User.Out:\n db[user_id] = User(**{**db[user_id].model_dump(), **user.model_dump(exclude_unset=True)})\n return db[user_id]\n\n\ndef test_fastapi():\n client = TestClient(app)\n\n # POST\n response = client.post(\n \"/users\",\n json={\n \"username\": \"admin\",\n \"password\": \"admin\",\n },\n )\n assert response.status_code == 200, response.text\n assert response.json() == {\n \"id\": 0,\n \"username\": \"admin\",\n \"settings\": {\"public\": None},\n }\n\n # GET\n response = client.get(\"/users/0\")\n assert response.status_code == 200, response.text\n assert response.json() == {\n \"id\": 0,\n \"username\": \"admin\",\n \"settings\": {\"public\": None},\n }\n\n # PUT\n response = client.put(\n \"/users/0\",\n json={\n \"username\": \"superadmin\",\n \"password\": \"superadmin\",\n \"settings\": {\"public\": \"foo\", \"secret\": \"secret\"},\n },\n )\n assert response.status_code == 200, response.text\n assert response.json() == {\n \"id\": 0,\n \"username\": \"superadmin\",\n \"settings\": {\"public\": \"foo\"},\n }\n\n # PATCH\n response = client.patch(\n \"/users/0\",\n json={\n \"username\": \"guest\",\n \"settings\": {\"public\": \"bar\"},\n },\n )\n assert response.status_code == 200, response.text\n assert response.json() == {\n \"id\": 0,\n \"username\": \"guest\",\n \"settings\": {\"public\": \"bar\"},\n }\n```\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "View decorator to create the child pydantic models from the root model.",
"version": "2.0.1",
"project_urls": null,
"split_keywords": [
"pydantic",
" model",
" view",
" utils"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "a5c920656e45feab1c718e6c517b0eaae16e83637669e892497855bc6d0b328e",
"md5": "b32bdda3d6b9fe3d74759b468b5e909c",
"sha256": "2c5d1e5caa6ff87c0d060cb370b0c23c27d43e829596ebe69245ce7189fb77dc"
},
"downloads": -1,
"filename": "pydantic_view-2.0.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "b32bdda3d6b9fe3d74759b468b5e909c",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0,>=3.8",
"size": 5957,
"upload_time": "2024-10-14T14:34:37",
"upload_time_iso_8601": "2024-10-14T14:34:37.532240Z",
"url": "https://files.pythonhosted.org/packages/a5/c9/20656e45feab1c718e6c517b0eaae16e83637669e892497855bc6d0b328e/pydantic_view-2.0.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "15ea21092800171d05350416222981038dbfcbbb4240c01385b4e2a08b3d8975",
"md5": "d775a8e899273410d169836b8d54d180",
"sha256": "e3b3cd3a079b5a977f2168b157aa599ba205a458dace128a15c45d02fc9778b3"
},
"downloads": -1,
"filename": "pydantic_view-2.0.1.tar.gz",
"has_sig": false,
"md5_digest": "d775a8e899273410d169836b8d54d180",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4.0,>=3.8",
"size": 5430,
"upload_time": "2024-10-14T14:34:39",
"upload_time_iso_8601": "2024-10-14T14:34:39.033187Z",
"url": "https://files.pythonhosted.org/packages/15/ea/21092800171d05350416222981038dbfcbbb4240c01385b4e2a08b3d8975/pydantic_view-2.0.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-10-14 14:34:39",
"github": false,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"lcname": "pydantic-view"
}