fastapi-crud-generator 0.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. fastapi_crud_generator-0.0.1/.github/workflows/docs.yml +25 -0
  2. fastapi_crud_generator-0.0.1/.github/workflows/release.yml +32 -0
  3. fastapi_crud_generator-0.0.1/.github/workflows/tests.yml +105 -0
  4. fastapi_crud_generator-0.0.1/.gitignore +38 -0
  5. fastapi_crud_generator-0.0.1/LICENSE.txt +21 -0
  6. fastapi_crud_generator-0.0.1/PKG-INFO +109 -0
  7. fastapi_crud_generator-0.0.1/README.md +56 -0
  8. fastapi_crud_generator-0.0.1/docs/api-reference.md +37 -0
  9. fastapi_crud_generator-0.0.1/docs/custom-adapter.md +120 -0
  10. fastapi_crud_generator-0.0.1/docs/guide/customization.md +70 -0
  11. fastapi_crud_generator-0.0.1/docs/guide/dependencies.md +58 -0
  12. fastapi_crud_generator-0.0.1/docs/guide/filtering-sorting.md +69 -0
  13. fastapi_crud_generator-0.0.1/docs/guide/getting-started.md +109 -0
  14. fastapi_crud_generator-0.0.1/docs/guide/nested-resources.md +74 -0
  15. fastapi_crud_generator-0.0.1/docs/guide/orm-adapters.md +102 -0
  16. fastapi_crud_generator-0.0.1/docs/guide/pagination.md +50 -0
  17. fastapi_crud_generator-0.0.1/docs/guide/schema-generation.md +105 -0
  18. fastapi_crud_generator-0.0.1/docs/index.md +62 -0
  19. fastapi_crud_generator-0.0.1/examples/__init__.py +0 -0
  20. fastapi_crud_generator-0.0.1/examples/forum/__init__.py +0 -0
  21. fastapi_crud_generator-0.0.1/examples/forum/orm/__init__.py +0 -0
  22. fastapi_crud_generator-0.0.1/examples/forum/orm/sqlalchemy.py +101 -0
  23. fastapi_crud_generator-0.0.1/examples/forum/orm/sqlmodel.py +106 -0
  24. fastapi_crud_generator-0.0.1/examples/forum/orm/tortoise.py +77 -0
  25. fastapi_crud_generator-0.0.1/fastapi_crud_generator/__init__.py +9 -0
  26. fastapi_crud_generator-0.0.1/fastapi_crud_generator/config.py +50 -0
  27. fastapi_crud_generator-0.0.1/fastapi_crud_generator/crud_generator.py +587 -0
  28. fastapi_crud_generator-0.0.1/fastapi_crud_generator/deps.py +275 -0
  29. fastapi_crud_generator-0.0.1/fastapi_crud_generator/orm/__init__.py +0 -0
  30. fastapi_crud_generator-0.0.1/fastapi_crud_generator/orm/base.py +169 -0
  31. fastapi_crud_generator-0.0.1/fastapi_crud_generator/orm/sqlalchemy.py +551 -0
  32. fastapi_crud_generator-0.0.1/fastapi_crud_generator/orm/sqlmodel.py +504 -0
  33. fastapi_crud_generator-0.0.1/fastapi_crud_generator/orm/tortoise.py +521 -0
  34. fastapi_crud_generator-0.0.1/fastapi_crud_generator/paginator.py +47 -0
  35. fastapi_crud_generator-0.0.1/fastapi_crud_generator/schemas.py +43 -0
  36. fastapi_crud_generator-0.0.1/fastapi_crud_generator/strategies.py +144 -0
  37. fastapi_crud_generator-0.0.1/fastapi_crud_generator/utils.py +138 -0
  38. fastapi_crud_generator-0.0.1/mkdocs.yml +62 -0
  39. fastapi_crud_generator-0.0.1/pyproject.toml +85 -0
  40. fastapi_crud_generator-0.0.1/tests/__init__.py +0 -0
  41. fastapi_crud_generator-0.0.1/tests/integration/__init__.py +0 -0
  42. fastapi_crud_generator-0.0.1/tests/integration/backends/__init__.py +12 -0
  43. fastapi_crud_generator-0.0.1/tests/integration/backends/sqlalchemy.py +73 -0
  44. fastapi_crud_generator-0.0.1/tests/integration/backends/sqlmodel.py +81 -0
  45. fastapi_crud_generator-0.0.1/tests/integration/backends/tortoise.py +113 -0
  46. fastapi_crud_generator-0.0.1/tests/integration/conftest.py +222 -0
  47. fastapi_crud_generator-0.0.1/tests/integration/test_basic.py +51 -0
  48. fastapi_crud_generator-0.0.1/tests/integration/test_composite.py +102 -0
  49. fastapi_crud_generator-0.0.1/tests/integration/test_include.py +251 -0
  50. fastapi_crud_generator-0.0.1/tests/integration/test_nested.py +129 -0
  51. fastapi_crud_generator-0.0.1/tests/integration/test_root_posts.py +65 -0
  52. fastapi_crud_generator-0.0.1/tests/integration/test_user_posts.py +78 -0
  53. fastapi_crud_generator-0.0.1/tests/test_deps.py +384 -0
  54. fastapi_crud_generator-0.0.1/tests/test_sqlmodel_crud_collection_pk.py +93 -0
  55. fastapi_crud_generator-0.0.1/tests/test_sqlmodel_schema_generation.py +202 -0
  56. fastapi_crud_generator-0.0.1/tests/test_utils_filter_model.py +73 -0
  57. fastapi_crud_generator-0.0.1/tests/test_utils_model_builders.py +59 -0
  58. fastapi_crud_generator-0.0.1/tests/test_utils_pydantic_field.py +82 -0
  59. fastapi_crud_generator-0.0.1/tests/test_utils_sort_schema.py +75 -0
  60. fastapi_crud_generator-0.0.1/uv.lock +1345 -0
@@ -0,0 +1,25 @@
1
+ name: Docs
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ paths:
8
+ - "docs/**"
9
+ - "mkdocs.yml"
10
+ - "fastapi_crud_generator/**" # docstrings in source
11
+
12
+ jobs:
13
+ deploy:
14
+ name: Build & deploy
15
+ runs-on: ubuntu-latest
16
+ permissions:
17
+ contents: write # push to gh-pages branch
18
+
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+
22
+ - uses: astral-sh/setup-uv@v5
23
+
24
+ - name: Deploy docs
25
+ run: uv run --group docs mkdocs gh-deploy --force
@@ -0,0 +1,32 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ jobs:
9
+ release:
10
+ name: Build & publish
11
+ runs-on: ubuntu-latest
12
+ environment: pypi
13
+ permissions:
14
+ contents: write # create GitHub release
15
+ id-token: write # OIDC token for PyPI trusted publisher
16
+
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+
20
+ - uses: astral-sh/setup-uv@v5
21
+
22
+ - name: Build
23
+ run: uv build
24
+
25
+ - name: Create GitHub Release
26
+ uses: softprops/action-gh-release@v2
27
+ with:
28
+ generate_release_notes: true
29
+ files: dist/*
30
+
31
+ - name: Publish to PyPI
32
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,105 @@
1
+ name: Tests
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ jobs:
9
+ unit:
10
+ name: unit tests
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+ - uses: astral-sh/setup-uv@v5
15
+ - name: Install dependencies
16
+ run: uv sync --group dev --group sqlmodel
17
+ - name: Run unit tests
18
+ run: uv run pytest tests/ --ignore=tests/integration/ -q
19
+
20
+ test:
21
+ name: ${{ matrix.orm }} / ${{ matrix.db }}
22
+ runs-on: ubuntu-latest
23
+
24
+ services:
25
+ postgres:
26
+ image: postgres:16
27
+ env:
28
+ POSTGRES_PASSWORD: postgres
29
+ POSTGRES_DB: test
30
+ ports:
31
+ - 5432:5432
32
+ options: >-
33
+ --health-cmd pg_isready
34
+ --health-interval 10s
35
+ --health-timeout 5s
36
+ --health-retries 5
37
+
38
+ mysql:
39
+ image: mysql:8
40
+ env:
41
+ MYSQL_ROOT_PASSWORD: mysql
42
+ MYSQL_DATABASE: test
43
+ ports:
44
+ - 3306:3306
45
+ options: >-
46
+ --health-cmd "mysqladmin ping -pmysql"
47
+ --health-interval 10s
48
+ --health-timeout 5s
49
+ --health-retries 5
50
+
51
+ strategy:
52
+ fail-fast: false
53
+ matrix:
54
+ include:
55
+ - orm: sqlmodel
56
+ db: sqlite
57
+ uv_groups: "--group sqlmodel --group sqlite"
58
+ - orm: sqlalchemy
59
+ db: sqlite
60
+ uv_groups: "--group sqlalchemy --group sqlite"
61
+ - orm: tortoise
62
+ db: sqlite
63
+ uv_groups: "--group tortoise --group sqlite"
64
+
65
+ - orm: sqlmodel
66
+ db: postgres
67
+ uv_groups: "--group sqlmodel --group postgresql"
68
+ postgres_url: postgresql+asyncpg://postgres:postgres@localhost/test
69
+ - orm: sqlalchemy
70
+ db: postgres
71
+ uv_groups: "--group sqlalchemy --group postgresql"
72
+ postgres_url: postgresql+asyncpg://postgres:postgres@localhost/test
73
+ - orm: tortoise
74
+ db: postgres
75
+ uv_groups: "--group tortoise --group postgresql"
76
+ postgres_url: postgresql+asyncpg://postgres:postgres@localhost/test
77
+
78
+ - orm: sqlmodel
79
+ db: mysql
80
+ uv_groups: "--group sqlmodel --group mysql"
81
+ mysql_url: mysql+aiomysql://root:mysql@localhost/test
82
+ - orm: sqlalchemy
83
+ db: mysql
84
+ uv_groups: "--group sqlalchemy --group mysql"
85
+ mysql_url: mysql+aiomysql://root:mysql@localhost/test
86
+ - orm: tortoise
87
+ db: mysql
88
+ uv_groups: "--group tortoise --group mysql"
89
+ mysql_url: mysql+aiomysql://root:mysql@localhost/test
90
+
91
+ steps:
92
+ - uses: actions/checkout@v4
93
+
94
+ - uses: astral-sh/setup-uv@v5
95
+
96
+ - name: Install dependencies
97
+ run: uv sync --group dev ${{ matrix.uv_groups }}
98
+
99
+ - name: Run tests
100
+ run: uv run pytest tests/integration/ -q
101
+ env:
102
+ PYTEST_ORM: ${{ matrix.orm }}
103
+ PYTEST_DB: ${{ matrix.db }}
104
+ POSTGRES_URL: ${{ matrix.postgres_url }}
105
+ MYSQL_URL: ${{ matrix.mysql_url }}
@@ -0,0 +1,38 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.pyo
5
+ *.pyd
6
+ .Python
7
+
8
+ # Virtual environments
9
+ .venv/
10
+ venv/
11
+ env/
12
+
13
+ # Build / distribution
14
+ dist/
15
+ build/
16
+ *.egg-info/
17
+ *.egg
18
+
19
+ # uv
20
+ .uv/
21
+
22
+ # pytest
23
+ .pytest_cache/
24
+ .coverage
25
+ htmlcov/
26
+
27
+ # IDE
28
+ .vscode/
29
+ .idea/
30
+ *.swp
31
+
32
+ # Jupyter
33
+ jupyter/
34
+ *.ipynb
35
+
36
+ # MkDocs
37
+ site/
38
+ TEST_MATRIX.md
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2026 Nikolai Lukianov
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,109 @@
1
+ Metadata-Version: 2.4
2
+ Name: fastapi-crud-generator
3
+ Version: 0.0.1
4
+ Summary: CRUD route generator for FastAPI
5
+ Project-URL: Homepage, https://github.com/mozgsml/fastapi_crud_generator
6
+ Project-URL: Repository, https://github.com/mozgsml/fastapi_crud_generator
7
+ Project-URL: Issues, https://github.com/mozgsml/fastapi_crud_generator/issues
8
+ Author-email: Nikolai Lukianov <laserwargpt@gmail.com>
9
+ License: The MIT License (MIT)
10
+
11
+ Copyright (c) 2026 Nikolai Lukianov
12
+
13
+ Permission is hereby granted, free of charge, to any person obtaining a copy
14
+ of this software and associated documentation files (the "Software"), to deal
15
+ in the Software without restriction, including without limitation the rights
16
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17
+ copies of the Software, and to permit persons to whom the Software is
18
+ furnished to do so, subject to the following conditions:
19
+
20
+ The above copyright notice and this permission notice shall be included in
21
+ all copies or substantial portions of the Software.
22
+
23
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29
+ THE SOFTWARE.
30
+ License-File: LICENSE.txt
31
+ Keywords: api,crud,fastapi,rest,sqlalchemy,sqlmodel,tortoise
32
+ Classifier: Development Status :: 3 - Alpha
33
+ Classifier: Framework :: FastAPI
34
+ Classifier: Intended Audience :: Developers
35
+ Classifier: License :: OSI Approved :: MIT License
36
+ Classifier: Programming Language :: Python :: 3
37
+ Classifier: Programming Language :: Python :: 3.11
38
+ Classifier: Programming Language :: Python :: 3.12
39
+ Classifier: Programming Language :: Python :: 3.13
40
+ Classifier: Topic :: Internet :: WWW/HTTP
41
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
42
+ Classifier: Typing :: Typed
43
+ Requires-Python: >=3.11
44
+ Requires-Dist: fastapi
45
+ Requires-Dist: pydantic
46
+ Provides-Extra: sqlalchemy
47
+ Requires-Dist: sqlalchemy[asyncio]; extra == 'sqlalchemy'
48
+ Provides-Extra: sqlmodel
49
+ Requires-Dist: sqlmodel; extra == 'sqlmodel'
50
+ Provides-Extra: tortoise
51
+ Requires-Dist: tortoise-orm>=1.1.7; extra == 'tortoise'
52
+ Description-Content-Type: text/markdown
53
+
54
+ # fastapi-crud-generator
55
+
56
+ [![Tests](https://github.com/mozgsml/fastapi_crud_generator/actions/workflows/tests.yml/badge.svg)](https://github.com/mozgsml/fastapi_crud_generator/actions/workflows/tests.yml)
57
+ [![PyPI](https://img.shields.io/pypi/v/fastapi-crud-generator)](https://pypi.org/project/fastapi-crud-generator/)
58
+ [![Python](https://img.shields.io/pypi/pyversions/fastapi-crud-generator)](https://pypi.org/project/fastapi-crud-generator/)
59
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE.txt)
60
+
61
+ Adds full CRUD routes to FastAPI without writing schemas, filters, or pagination by hand.
62
+ Everything is generated automatically from your ORM model.
63
+
64
+ ```python
65
+ from fastapi_crud_generator import CRUDCollection
66
+ from fastapi_crud_generator.orm.sqlmodel import SQLModelAdapter
67
+
68
+ crud = CRUDCollection(orm_adapter=SQLModelAdapter(model=Article, get_session=get_session))
69
+ app.include_router(crud.get_router(prefix="/articles", tags=["articles"]))
70
+ ```
71
+
72
+ Three lines — and five endpoints are ready with filtering, sorting, and pagination:
73
+
74
+ ```
75
+ GET /articles ?title=…&published=true&sort=created_at:desc&page=1&per_page=20
76
+ GET /articles/{article_id}
77
+ POST /articles
78
+ PATCH /articles/{article_id}
79
+ DELETE /articles/{article_id}
80
+ ```
81
+
82
+ ## Installation
83
+
84
+ If SQLModel, SQLAlchemy, or Tortoise is already in your project:
85
+
86
+ ```bash
87
+ pip install fastapi-crud-generator
88
+ ```
89
+
90
+ To install an ORM together with the package:
91
+
92
+ ```bash
93
+ pip install "fastapi-crud-generator[sqlmodel]"
94
+ pip install "fastapi-crud-generator[sqlalchemy]"
95
+ pip install "fastapi-crud-generator[tortoise]"
96
+ ```
97
+
98
+ ## Documentation
99
+
100
+ **[mozgsml.github.io/fastapi_crud_generator](https://mozgsml.github.io/fastapi_crud_generator)**
101
+
102
+ - [Getting Started](https://mozgsml.github.io/fastapi_crud_generator/guide/getting-started/) — full working example from scratch
103
+ - [Schema Generation](https://mozgsml.github.io/fastapi_crud_generator/guide/schema-generation/) — control which fields appear in each schema
104
+ - [Nested Resources](https://mozgsml.github.io/fastapi_crud_generator/guide/nested-resources/) — `/threads/{id}/posts/{id}`
105
+ - [Custom Adapter](https://mozgsml.github.io/fastapi_crud_generator/custom-adapter/) — connect your own ORM
106
+
107
+ ## License
108
+
109
+ MIT
@@ -0,0 +1,56 @@
1
+ # fastapi-crud-generator
2
+
3
+ [![Tests](https://github.com/mozgsml/fastapi_crud_generator/actions/workflows/tests.yml/badge.svg)](https://github.com/mozgsml/fastapi_crud_generator/actions/workflows/tests.yml)
4
+ [![PyPI](https://img.shields.io/pypi/v/fastapi-crud-generator)](https://pypi.org/project/fastapi-crud-generator/)
5
+ [![Python](https://img.shields.io/pypi/pyversions/fastapi-crud-generator)](https://pypi.org/project/fastapi-crud-generator/)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE.txt)
7
+
8
+ Adds full CRUD routes to FastAPI without writing schemas, filters, or pagination by hand.
9
+ Everything is generated automatically from your ORM model.
10
+
11
+ ```python
12
+ from fastapi_crud_generator import CRUDCollection
13
+ from fastapi_crud_generator.orm.sqlmodel import SQLModelAdapter
14
+
15
+ crud = CRUDCollection(orm_adapter=SQLModelAdapter(model=Article, get_session=get_session))
16
+ app.include_router(crud.get_router(prefix="/articles", tags=["articles"]))
17
+ ```
18
+
19
+ Three lines — and five endpoints are ready with filtering, sorting, and pagination:
20
+
21
+ ```
22
+ GET /articles ?title=…&published=true&sort=created_at:desc&page=1&per_page=20
23
+ GET /articles/{article_id}
24
+ POST /articles
25
+ PATCH /articles/{article_id}
26
+ DELETE /articles/{article_id}
27
+ ```
28
+
29
+ ## Installation
30
+
31
+ If SQLModel, SQLAlchemy, or Tortoise is already in your project:
32
+
33
+ ```bash
34
+ pip install fastapi-crud-generator
35
+ ```
36
+
37
+ To install an ORM together with the package:
38
+
39
+ ```bash
40
+ pip install "fastapi-crud-generator[sqlmodel]"
41
+ pip install "fastapi-crud-generator[sqlalchemy]"
42
+ pip install "fastapi-crud-generator[tortoise]"
43
+ ```
44
+
45
+ ## Documentation
46
+
47
+ **[mozgsml.github.io/fastapi_crud_generator](https://mozgsml.github.io/fastapi_crud_generator)**
48
+
49
+ - [Getting Started](https://mozgsml.github.io/fastapi_crud_generator/guide/getting-started/) — full working example from scratch
50
+ - [Schema Generation](https://mozgsml.github.io/fastapi_crud_generator/guide/schema-generation/) — control which fields appear in each schema
51
+ - [Nested Resources](https://mozgsml.github.io/fastapi_crud_generator/guide/nested-resources/) — `/threads/{id}/posts/{id}`
52
+ - [Custom Adapter](https://mozgsml.github.io/fastapi_crud_generator/custom-adapter/) — connect your own ORM
53
+
54
+ ## License
55
+
56
+ MIT
@@ -0,0 +1,37 @@
1
+ # API Reference
2
+
3
+ ## CRUDCollection
4
+
5
+ ::: fastapi_crud_generator.crud_generator.CRUDCollection
6
+
7
+ ::: fastapi_crud_generator.crud_generator.CRUDCollectionBase
8
+
9
+ ## Adapters
10
+
11
+ ::: fastapi_crud_generator.orm.sqlmodel.SQLModelAdapter
12
+
13
+ ::: fastapi_crud_generator.orm.sqlalchemy.SQLAlchemyAdapter
14
+
15
+ ::: fastapi_crud_generator.orm.tortoise.TortoiseAdapter
16
+
17
+ ::: fastapi_crud_generator.orm.base.ORMAdapterBase
18
+
19
+ ## Configuration
20
+
21
+ ::: fastapi_crud_generator.config.CRUDConfigDict
22
+
23
+ ::: fastapi_crud_generator.config.NestedConfig
24
+
25
+ ## Pagination
26
+
27
+ ::: fastapi_crud_generator.paginator.PaginatorBase
28
+
29
+ ::: fastapi_crud_generator.schemas.PaginatorPage
30
+
31
+ ## Schemas & Errors
32
+
33
+ ::: fastapi_crud_generator.schemas.ParentRef
34
+
35
+ ::: fastapi_crud_generator.schemas.NotFoundError
36
+
37
+ ::: fastapi_crud_generator.schemas.ParentNotFoundError
@@ -0,0 +1,120 @@
1
+ # Custom Adapter
2
+
3
+ To connect an ORM or data source that has no built-in adapter, implement `ORMAdapterBase`.
4
+
5
+ ## Interface
6
+
7
+ ```python
8
+ from fastapi_crud_generator.orm.base import ORMAdapterBase
9
+ from fastapi_crud_generator.schemas import PaginatorPage, ParentRef
10
+ from pydantic import BaseModel
11
+
12
+ class MyAdapter(ORMAdapterBase):
13
+ # Schema generation
14
+ def generate_public_schema(self, fields=None, base_fields=None) -> type[BaseModel]: ...
15
+ def generate_create_schema(self, fields=None, base_fields=None, exclude_related=None) -> type[BaseModel]: ...
16
+ def generate_update_schema(self, fields=None, base_fields=None) -> type[BaseModel]: ...
17
+ def generate_pk_schema(self) -> type[BaseModel]: ...
18
+ def generate_include_schema(self) -> type[BaseModel]: ...
19
+
20
+ # CRUD operations
21
+ async def get_one(self, pk_values, include_data, parent_refs=None): ...
22
+ async def get_many(self, filter_data, sort_data, include_data, paginator, parent_refs=None): ...
23
+ async def create_one(self, data, parent_refs=None): ...
24
+ async def update_one(self, pk_values, data, parent_refs=None): ...
25
+ async def delete_one(self, pk_values, parent_refs=None): ...
26
+ ```
27
+
28
+ ## Example: in-memory store
29
+
30
+ ```python
31
+ from pydantic import BaseModel, create_model
32
+ from fastapi_crud_generator.orm.base import ORMAdapterBase
33
+ from fastapi_crud_generator.schemas import NotFoundError
34
+
35
+ _store: dict[int, dict] = {}
36
+ _next_id = 1
37
+
38
+ class ItemPublic(BaseModel):
39
+ id: int
40
+ name: str
41
+ price: float
42
+
43
+ class ItemCreate(BaseModel):
44
+ name: str
45
+ price: float
46
+
47
+ class ItemUpdate(BaseModel):
48
+ name: str | None = None
49
+ price: float | None = None
50
+
51
+ class ItemPK(BaseModel):
52
+ id: int
53
+
54
+ class InMemoryAdapter(ORMAdapterBase):
55
+ def generate_public_schema(self, fields=None, base_fields=None):
56
+ return ItemPublic
57
+
58
+ def generate_create_schema(self, fields=None, base_fields=None, exclude_related=None):
59
+ return ItemCreate
60
+
61
+ def generate_update_schema(self, fields=None, base_fields=None):
62
+ return ItemUpdate
63
+
64
+ def generate_pk_schema(self):
65
+ return ItemPK
66
+
67
+ def generate_include_schema(self):
68
+ return create_model("ItemInclude")
69
+
70
+ async def get_one(self, pk_values, include_data, parent_refs=None):
71
+ return _store.get(pk_values.id)
72
+
73
+ async def get_many(self, filter_data, sort_data, include_data, paginator, parent_refs=None):
74
+ items = list(_store.values())
75
+ page = items[paginator.offset : paginator.offset + paginator.limit]
76
+ return {"page": paginator.page, "per_page": paginator.per_page, "count": len(items), "data": page}
77
+
78
+ async def create_one(self, data, parent_refs=None):
79
+ global _next_id
80
+ item = {"id": _next_id, **data.model_dump()}
81
+ _store[_next_id] = item
82
+ _next_id += 1
83
+ return item
84
+
85
+ async def update_one(self, pk_values, data, parent_refs=None):
86
+ if pk_values.id not in _store:
87
+ raise NotFoundError
88
+ for k, v in data.model_dump(exclude_none=True).items():
89
+ _store[pk_values.id][k] = v
90
+
91
+ async def delete_one(self, pk_values, parent_refs=None):
92
+ return _store.pop(pk_values.id, None)
93
+ ```
94
+
95
+ Usage:
96
+
97
+ ```python
98
+ crud = CRUDCollection(orm_adapter=InMemoryAdapter())
99
+ app.include_router(crud.get_router(prefix="/items"))
100
+ ```
101
+
102
+ ## `parent_refs` in nested resources
103
+
104
+ In nested routes, CRUD methods receive `parent_refs` — a list of `ParentRef`
105
+ objects describing the parent items in the URL:
106
+
107
+ ```python
108
+ from fastapi_crud_generator.schemas import ParentRef
109
+
110
+ async def get_many(self, filter_data, sort_data, include_data, paginator, parent_refs=None):
111
+ query = select(Post)
112
+ for ref in (parent_refs or []):
113
+ if ref.model is Thread:
114
+ query = query.where(Post.thread_id == ref.pk_values.thread_id)
115
+ ...
116
+ ```
117
+
118
+ ## Full interface reference
119
+
120
+ See [API Reference](api-reference.md).
@@ -0,0 +1,70 @@
1
+ # Customization
2
+
3
+ ## Disabling endpoints
4
+
5
+ ```python
6
+ crud = CRUDCollection(
7
+ orm_adapter=adapter,
8
+ disable_delete=True,
9
+ disable_create=True,
10
+ )
11
+ ```
12
+
13
+ ## Overriding handlers via subclass
14
+
15
+ Subclass `CRUDCollection` and override the methods you need:
16
+
17
+ ```python
18
+ from fastapi_crud_generator import CRUDCollection
19
+ from fastapi_crud_generator.orm.sqlmodel import SQLModelAdapter
20
+
21
+ class ArticleCRUD(CRUDCollection):
22
+ orm_adapter = SQLModelAdapter(model=Article, get_session=get_session)
23
+
24
+ async def get_one_not_found(self, pk_values, include_data):
25
+ raise HTTPException(status_code=404, detail="Article not found")
26
+
27
+ async def create_one_handler(self, create_data, parent_refs):
28
+ create_data.slug = slugify(create_data.title)
29
+ return await super().create_one_handler(create_data, parent_refs)
30
+
31
+ crud = ArticleCRUD()
32
+ app.include_router(crud.get_router(prefix="/articles"))
33
+ ```
34
+
35
+ ## Class attributes instead of constructor arguments
36
+
37
+ All `CRUDCollection` parameters can be set as class attributes:
38
+
39
+ ```python
40
+ class ArticleCRUD(CRUDCollection):
41
+ orm_adapter = SQLModelAdapter(model=Article, get_session=get_session)
42
+ disable_delete = True
43
+ dependencies = [Depends(require_auth)]
44
+ create_dependencies = [Depends(require_admin)]
45
+ ```
46
+
47
+ This is handy when several collections share common configuration:
48
+
49
+ ```python
50
+ class AuthenticatedCRUD(CRUDCollection):
51
+ dependencies = [Depends(require_auth)]
52
+
53
+ class ArticleCRUD(AuthenticatedCRUD):
54
+ orm_adapter = SQLModelAdapter(model=Article, get_session=get_session)
55
+
56
+ class CommentCRUD(AuthenticatedCRUD):
57
+ orm_adapter = SQLModelAdapter(model=Comment, get_session=get_session)
58
+ ```
59
+
60
+ ## Custom ID path
61
+
62
+ By default, `CRUDCollection` builds a path like `/{article_id}` from the model name.
63
+ Override `apply_pk_aliases` to change this:
64
+
65
+ ```python
66
+ class ArticleCRUD(CRUDCollection):
67
+ def apply_pk_aliases(self, pk_schema):
68
+ # use /{id} instead of /{article_id}
69
+ return pk_schema
70
+ ```
@@ -0,0 +1,58 @@
1
+ # Dependencies
2
+
3
+ Standard FastAPI dependencies (`Depends`) can be applied to all routes at once
4
+ or to a specific operation type.
5
+
6
+ ## All routes
7
+
8
+ ```python
9
+ from fastapi import Depends
10
+ from fastapi_crud_generator import CRUDCollection
11
+
12
+ crud = CRUDCollection(
13
+ orm_adapter=adapter,
14
+ dependencies=[Depends(require_auth)],
15
+ )
16
+ ```
17
+
18
+ ## Per operation type
19
+
20
+ ```python
21
+ crud = CRUDCollection(
22
+ orm_adapter=adapter,
23
+ get_one_dependencies=[Depends(require_auth)],
24
+ get_many_dependencies=[Depends(require_auth)],
25
+ create_dependencies=[Depends(require_admin)],
26
+ update_dependencies=[Depends(require_admin)],
27
+ delete_dependencies=[Depends(require_admin)],
28
+ )
29
+ ```
30
+
31
+ ## Example: JWT authentication
32
+
33
+ ```python
34
+ from fastapi import Depends, HTTPException, Security
35
+ from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
36
+
37
+ security = HTTPBearer()
38
+
39
+ async def require_auth(credentials: HTTPAuthorizationCredentials = Security(security)):
40
+ if not verify_token(credentials.credentials):
41
+ raise HTTPException(status_code=401, detail="Unauthorized")
42
+
43
+ crud = CRUDCollection(
44
+ orm_adapter=adapter,
45
+ dependencies=[Depends(require_auth)],
46
+ )
47
+ ```
48
+
49
+ ## At router level
50
+
51
+ Dependencies can also be added when mounting the router rather than in `CRUDCollection`:
52
+
53
+ ```python
54
+ app.include_router(
55
+ crud.get_router(prefix="/articles"),
56
+ dependencies=[Depends(require_auth)],
57
+ )
58
+ ```