{"id":15041149,"url":"https://github.com/codemation/pydbantic","last_synced_at":"2025-04-05T04:12:16.741Z","repository":{"id":41533679,"uuid":"402156856","full_name":"codemation/pydbantic","owner":"codemation","description":"A single model for shaping, creating, accessing, storing data within a Database","archived":false,"fork":false,"pushed_at":"2023-10-03T08:00:16.000Z","size":351,"stargazers_count":235,"open_issues_count":6,"forks_count":15,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-29T03:07:37.087Z","etag":null,"topics":["async","database","databases","models","orm","pydantic","python","redis","sqlalchemy"],"latest_commit_sha":null,"homepage":"https://pydbantic.readthedocs.io/en/latest/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/codemation.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-09-01T18:02:26.000Z","updated_at":"2025-03-07T15:13:08.000Z","dependencies_parsed_at":"2024-06-21T16:35:12.463Z","dependency_job_id":"60d6de91-992e-4156-8759-fd0d46ea5bb6","html_url":"https://github.com/codemation/pydbantic","commit_stats":{"total_commits":138,"total_committers":8,"mean_commits":17.25,"dds":0.1376811594202898,"last_synced_commit":"2256dfdb2476d0e625ef4697dff1486de4825009"},"previous_names":[],"tags_count":44,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codemation%2Fpydbantic","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codemation%2Fpydbantic/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codemation%2Fpydbantic/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codemation%2Fpydbantic/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/codemation","download_url":"https://codeload.github.com/codemation/pydbantic/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247284951,"owners_count":20913704,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["async","database","databases","models","orm","pydantic","python","redis","sqlalchemy"],"created_at":"2024-09-24T20:45:40.665Z","updated_at":"2025-04-05T04:12:16.718Z","avatar_url":"https://github.com/codemation.png","language":"Python","readme":"![](docs/images/logo.png)\n\nPersistent pydantic models - A single model for shaping, creating, accessing, storing data within a Database\n\n[![Documentation Status](https://readthedocs.org/projects/pydbantic/badge/?version=latest)](https://pydbantic.readthedocs.io/en/latest/?badge=latest) [![PyPI version](https://badge.fury.io/py/pydbantic.svg)](https://badge.fury.io/py/pydbantic)[![Unit \u0026 Integration Tests](https://github.com/codemation/pydbantic/actions/workflows/package.yaml/badge.svg)](https://github.com/codemation/pydbantic/actions/workflows/package.yaml)\n\n## Key Features\n- Flexible Data Types\n- One Model for type validation \u0026 database access\n- Dynamic / Explicit Model Relationships\n- Integrated Redis Caching Support\n- Built in support for Alembic Migrations or Automatic Migration on Schema Changes\n\n## Documentation\n[https://pydbantic.readthedocs.io/en/latest/](https://pydbantic.readthedocs.io/en/latest/)\n\n## Setup\n```bash\n$ pip install pydbantic\n$ pip install pydbantic[sqlite]\n$ pip install pydbantic[mysql]\n$ pip install pydbantic[postgres]\n```\n\n## Basic Usage - Model\n\n```python\nfrom typing import List, Optional, Union\nfrom pydbantic import DataBaseModel, PrimaryKey, Unique\n\nclass Department(DataBaseModel):\n    department_id: str = PrimaryKey()\n    name: str = Unique()\n    company: str\n    is_sensitive: bool = False\n    positions: List[Optional['Positions']] = []  # One to Many\n\nclass Positions(DataBaseModel):\n    position_id: str = PrimaryKey()\n    name: str\n    department: Department = None               # One to One mapping\n    employees: List[Optional['Employee']] = []  # One to Many\n\nclass EmployeeInfo(DataBaseModel):\n    ssn: str = PrimaryKey()\n    first_name: str\n    last_name: str\n    address: str\n    address2: Optional[str]\n    city: Optional[str]\n    zip: Optional[int]\n    new: Optional[str]\n    employee: Optional[Union['Employee', dict]] = None # One to One\n\nclass Employee(DataBaseModel):\n    employee_id: str = PrimaryKey()\n    employee_info: Optional[EmployeeInfo] = None  # One to One\n    position: List[Optional[Positions]] = []      # One to Many\n    salary: float\n    is_employed: bool\n    date_employed: Optional[str]\n```\n\n## Basic Usage - Connecting a Database to Models\n\n```python\nimport asyncio\nfrom pydbantic import Database\nfrom models import Employee, EmployeeInfo, Positions, Department\n\nasync def main():\n    db = await Database.create(\n        'sqlite:///test.db',\n        tables=[\n            Employee,\n            EmployeeInfo,\n            Positions,\n            Department\n        ]\n    )\n\nif __name__ == '__main__':\n    asyncio.run(main())\n```\n\n## Model Usage\n\nImport and use the models where you need them. As long as DB as already been created,\nthe Models can access the \u0026 Use the connected DB\n\n```python\nfrom models import (\n    Employee,\n    EmployeeInfo,\n    Position,\n    Department\n)\n\n```\n\n### Model - Creation\n\n```python\n    # create department\n    hr_department = await Department.create(\n        id='d1234',\n        name='hr'\n        company='abc-company',\n        is_sensitive=True,\n    )\n```\nVia instance using insert or save\n\n```python\n    hr_department = Department.create(\n        id='d1234',\n        name='hr'\n        company='abc-company',\n        is_sensitive=True,\n    )\n\n    await hr_department.insert()\n    await hr_department.save()\n```\n\nInsert with related models\n\n```python\n\n    # create a Position in Hr Department\n    hr_manager = Position.create(\n        id='p1234',\n        name='manager',\n        department=hr_department\n    )\n\n    # create instance on an hr employee\n    hr_emp_info = EmployeeInfo.create(\n        ssn='123-456-789',\n        first_name='john',\n        last_name='doe',\n        address='123 lane',\n        city='snake city',\n        zip=12345\n    )\n\n    # create an hr employee\n    hr_employee = await Employee.create(\n        id='e1234',\n        employee_info=hr_emp_info,\n        position=hr_manager,\n        is_employed=True,\n        date_employed='1970-01-01'\n    )\n```\n\n### Filtering\n```python\n    # get all hr managers currently employed\n    managers = await Employee.filter(\n        Employee.position==hr_manager, # conditional\n        is_employed=True               # key-word argument\n    )\n\n    first_100_employees = await Employee.all(\n        limit=100\n    )\n\n```\nSee also filtering [operators](https://pydbantic.readthedocs.io/en/latest/model-usage/#model-usage-query-filtering)\n\n\n### Deleting\n```python\n    # one by one\n    for manager in await Employee.filter(\n        position=hr_manager,\n        is_employed=False\n    ):\n        await manager.delete()\n```\n\n```python\n    # all at once\n    await Employee.delete_filter(\n        Employee.is_employed == True\n    )\n\n```\n\n### Updating\n```python\n    # raise salary of all managers\n    for manager in await Employee.filter(\n        position=hr_manager,\n        is_employed=False\n    ):\n        manager.salary = manager.salary + 1000.0\n        await manager.update() # or manager.save()\n```\n\n`.save()` results in a new row created in `Employee` table as well as the related `EmployeeInfo`, `Position`, `Department` tables if not yet created.  s\n\n## What is pydbantic\n`pydbantic` was built to solve some of the most common pain developers may face working with databases.\n- migrations\n- model creation / management\n- dynamic relationships\n- caching\n\n`pydbantic` believes that related data should be stored together, in the shape the developer plans to use\n\n`pydbantic` knows data is rarely flat or follows a set schema\n\n`pydbantic` understand migrations are not fun, and does them for you\n\n`pydbantic` speaks many `types`\n\n\n## Pillars\n- [pydantic](https://pydantic-docs.helpmanual.io/) - Models, Type validation\n- [databases](https://www.encode.io/databases/) - Database Connection Abstractions\n- [sqlalchemy](https://www.sqlalchemy.org/) - Core Database Query and Database Model\n\n## Models\n`pydbantic` most basic object is a `DataBaseModel`. This object may be comprised of almost any `pickle-able` python object, though you are encouraged to stay within the type-validation land by using `pydantic`'s `BaseModels` and validators.\n\n### Primary Keys\n`DataBaseModel` 's also have a primary key, which is the first item defined in a model or marked with `= PrimaryKey()`\n\n```python\nclass NotesBm(DataBaseModel):\n    id: str = PrimaryKey()\n    text: Optional[str]  # optional\n    data: DataModel      # required\n    coordinates: tuple   # required\n    items: list          # required\n    nested: dict = {'nested': True} # Optional - w/ Default\n```\n### Model Types \u0026 Typing\n`DataBaseModel` items are capable of being multiple layers deep following `pydantic` model validation\n- Primary Key - First Item, must be unique\n- Required - items without default values are assumed required\n- Optional - marked explicitly with `typing.Optional` or with a default value\n- Union - Accepts Either specified input type Union[str|int]\n- List[item] - Lists of specified items\n\nInput data-types without a standard built-in db serialization, are serialized using `pickle` and stored as bytes. More on this later.\n\n## Migrations\n`pydbantic` can handle migrations automatically in response to detected model changes: `New Field`, `Removed Field`, `Modified Field`, `Renamed Field`, `Primary Key Changes`.\n\n`pydbantic` is also able to integrate with Alembic to perform migrations, see [Migrations Using Alembic](https://pydbantic.readthedocs.io/en/latest/alembic/)\n\n\n## Cache\nAdding cache with Redis is easy with `pydbantic`, and is complete with built in `cache invalidation`. I.E when a query becomes outdated(from insertion / update / deletion), it will be expelled from cache.\n\n```python\n    db = await Database.create(\n        'sqlite:///test.db',\n        tables=[Employee],\n        cache_enabled=True,\n        redis_url=\"redis://localhost\"\n    )\n```\n\n## Models with arrays of Foreign Objects\n\n`DataBaseModel` models can support arrays of both `BaseModels` and other `DataBaseModel`. Just like single `DataBaseModel` references, data is stored in separate tables, and populated automatically when the child `DataBaseModel` is instantiated.\n\n```python\nfrom uuid import uuid4\nfrom datetime import datetime\nfrom typing import List, Optional\nfrom pydbantic import DataBaseModel, PrimaryKey\n\n\ndef time_now():\n    return datetime.now().isoformat()\ndef get_uuid4():\n    return str(uuid4())\n\nclass Coordinate(DataBaseModel):\n    id: str = PrimaryKey(default=get_uuid4)\n    lat_long: tuple\n    journeys: List[Optional[\"Journey\"]] = []\n\nclass Journey(DataBaseModel):\n    trip_id: str = PrimaryKey(default=get_uuid4)\n    waypoints: List[Optional[Coordinate]] = []\n\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodemation%2Fpydbantic","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcodemation%2Fpydbantic","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodemation%2Fpydbantic/lists"}