-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3 from so-saf/expand_docs
📝 Expand documentation
- Loading branch information
Showing
39 changed files
with
1,983 additions
and
81 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
name: Build Documentation | ||
|
||
on: | ||
push: | ||
branches: | ||
- master | ||
|
||
permissions: | ||
contents: write | ||
|
||
env: | ||
DEFAULT_PYTHON: "3.12" | ||
|
||
jobs: | ||
deploy: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- name: Configure Git Credentials | ||
run: | | ||
git config user.name github-actions[bot] | ||
git config user.email 41898282+github-actions[bot]@users.noreply.github.com | ||
- name: Set up Poetry | ||
run: pipx install poetry | ||
- name: Set up Python ${{ env.DEFAULT_PYTHON }} | ||
id: python | ||
uses: actions/setup-python@v5 | ||
with: | ||
python-version: ${{ env.DEFAULT_PYTHON }} | ||
cache: "poetry" | ||
- name: Install workflow dependencies | ||
run: | | ||
poetry config virtualenvs.create true | ||
poetry config virtualenvs.in-project true | ||
- name: Install dependencies | ||
run: poetry install --no-interaction | ||
- run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV | ||
- uses: actions/cache@v4 | ||
with: | ||
key: mkdocs-material-${{ env.cache_id }} | ||
path: .cache | ||
restore-keys: | | ||
mkdocs-material- | ||
- run: cd docs | ||
- run: mkdocs gh-deploy --force |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
|
||
|
||
::: pydantic_filters.drivers.sqlalchemy.append_filter_to_statement | ||
::: pydantic_filters.drivers.sqlalchemy.append_pagination_to_statement | ||
::: pydantic_filters.drivers.sqlalchemy.append_sort_to_statement | ||
::: pydantic_filters.drivers.sqlalchemy.append_to_statement | ||
::: pydantic_filters.drivers.sqlalchemy.get_count_statement | ||
::: pydantic_filters.drivers.sqlalchemy.BaseSaDriverError | ||
::: pydantic_filters.drivers.sqlalchemy.AttributeNotFoundSaDriverError | ||
::: pydantic_filters.drivers.sqlalchemy.RelationshipNotFoundSaDriverError | ||
::: pydantic_filters.drivers.sqlalchemy.SupportSaDriverError |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
|
||
::: pydantic_filters.BaseFilter |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
|
||
::: pydantic_filters.FilterConfigDict |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
|
||
::: pydantic_filters.FilterField | ||
|
||
::: pydantic_filters.SearchField | ||
|
||
::: pydantic_filters.filter._fields.FilterFieldInfo | ||
options: | ||
inherited_members: true | ||
|
||
::: pydantic_filters.filter._fields.SearchFieldInfo | ||
options: | ||
inherited_members: true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
|
||
::: pydantic_filters.FilterType | ||
::: pydantic_filters.filter.FilterTypeLiteral | ||
::: pydantic_filters.SearchType | ||
::: pydantic_filters.filter.SearchTypeLiteral | ||
::: pydantic_filters.filter._types._suffixes_map | ||
::: pydantic_filters.get_suffixes_map |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
|
||
::: pydantic_filters.BasePagination | ||
|
||
::: pydantic_filters.OffsetPagination | ||
options: | ||
inherited_members: true | ||
|
||
::: pydantic_filters.PagePagination | ||
options: | ||
inherited_members: true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
|
||
::: pydantic_filters.plugins.fastapi.FilterDepends | ||
::: pydantic_filters.plugins.fastapi.PaginationDepends | ||
::: pydantic_filters.plugins.fastapi.SortDepends |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
|
||
::: pydantic_filters.BaseSort | ||
|
||
::: pydantic_filters.SortByOrder |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
--- | ||
hide: | ||
- navigation | ||
- toc | ||
--- | ||
|
||
|
||
# pydantic-filters | ||
|
||
[![Testing](https://github.com/so-saf/pydantic-filters/actions/workflows/test.yaml/badge.svg)](https://github.com/so-saf/pydantic-filters/actions/workflows/test.yaml) | ||
[![pypi](https://img.shields.io/pypi/v/pydantic-filters.svg)](https://pypi.python.org/pypi/pydantic-filters) | ||
[![license](https://img.shields.io/github/license/so-saf/pydantic-filters.svg)](https://github.com/so-saf/pydantic-filters/blob/main/LICENSE) | ||
[![versions](https://img.shields.io/pypi/pyversions/pydantic-filters.svg)](https://github.com/so-saf/pydantic-filters) | ||
|
||
**Source Code:** [https://github.com/so-saf/pydantic-filters](https://github.com/so-saf/pydantic-filters) | ||
|
||
--- | ||
|
||
Describe the filters, not implement them! | ||
A declarative and intuitive way to describe data filtering and sorting in your application. | ||
|
||
# Features | ||
|
||
- Filtering by the models themselves as well as by related. | ||
- Built-in pagination and sorting. | ||
- Lots of settings and possible customizations. | ||
- The only required dependency is Pydantic. | ||
You can use the basic features without being attached to specific frameworks, | ||
or use one of the supported plugins and drivers: | ||
- Plugins: | ||
- FastAPI >= 0.100.0 | ||
- Drivers: | ||
- SQLAlchemy >= 2 | ||
|
||
# Installation | ||
|
||
```shell | ||
pip install pydantic-filters | ||
``` | ||
|
||
# A Simple Example | ||
|
||
`BaseFilter` is just a pydantic model, it should be treated similarly | ||
|
||
Let's imagine you have a simple user service with the following SQLAlchemy model: | ||
|
||
|
||
```python | ||
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column | ||
|
||
|
||
class Base(DeclarativeBase): | ||
pass | ||
|
||
|
||
class User(Base): | ||
__tablename__ = "users" | ||
id: Mapped[int] = mapped_column(primary_key=True) | ||
name: Mapped[str] | ||
age: Mapped[int] | ||
``` | ||
|
||
Describe how you would like to filter users using BaseFilter. | ||
|
||
```python | ||
from typing import List | ||
from pydantic_filters import BaseFilter | ||
|
||
|
||
class UserFilter(BaseFilter): | ||
id: List[int] | ||
name: List[str] | ||
name__ilike: str | ||
age__lt: int | ||
age__gt: int | ||
``` | ||
|
||
`BaseFilter` is just a pydantic model, it should be treated similarly | ||
|
||
Next, you need to apply a filter to some query: | ||
|
||
```python | ||
from sqlalchemy import select | ||
from pydantic_filters.drivers.sqlalchemy import append_filter_to_statement | ||
|
||
statement = select(User) | ||
filter_ = UserFilter(name__ilike="kate", age__lt=23) | ||
|
||
stmt = append_filter_to_statement( | ||
statement=statement, model=User, filter_=filter_, | ||
) | ||
``` | ||
|
||
And get something like: | ||
|
||
```sql | ||
SELECT users.id, users.name, users.age | ||
FROM users | ||
WHERE users.name ILIKE 'kate' AND users.age < 23 | ||
``` | ||
|
||
The filter can be used in conjunction with one of the supported web frameworks: | ||
|
||
```python | ||
from typing import Annotated | ||
from fastapi import FastAPI, APIRouter | ||
from pydantic_filters.plugins.fastapi import FilterDepends | ||
|
||
|
||
router = APIRouter() | ||
|
||
|
||
@router.get("/") | ||
async def get_multiple( | ||
filter_: Annotated[UserFilter, FilterDepends(UserFilter)], | ||
): | ||
... | ||
|
||
|
||
app = FastAPI(title="User Service") | ||
app.include_router(router, prefix="/users", tags=["User"]) | ||
``` | ||
|
||
![fastapi-simple-example.png](images/fastapi-simple-example.png) |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
|
||
`FastAPI` is a modern and fast web framework for Python. | ||
|
||
`pydantic-filters` provides several features for integrations: | ||
[`FilterDepends`][pydantic_filters.plugins.fastapi.FilterDepends], | ||
[`PaginationDepends`][pydantic_filters.plugins.fastapi.PaginationDepends] and | ||
[`SortDepends`][pydantic_filters.plugins.fastapi.SortDepends]. | ||
Each of the functions unpacks the pydantic model and convert `pydantic.FieldInfo` | ||
fields to `fastapi.Query`. | ||
|
||
## Example | ||
|
||
```python | ||
from enum import Enum | ||
from typing import List, Optional | ||
|
||
from fastapi import FastAPI | ||
from pydantic_filters import BaseFilter, BaseSort, FilterField, OffsetPagination, SearchField | ||
from pydantic_filters.plugins.fastapi import FilterDepends, PaginationDepends, SortDepends | ||
|
||
|
||
class DepartmentFilter(BaseFilter): | ||
chef_id: List[int] = FilterField(description="Here is the related field!!!") | ||
|
||
|
||
class UserFilter(BaseFilter): | ||
login: List[str] | ||
age__lt: int = FilterField(gt=0, le=100) | ||
q: str = SearchField(target=["login", "name", "email"]) | ||
# Related filter! | ||
department: DepartmentFilter | ||
|
||
|
||
class UserSortByEnum(str, Enum): | ||
id = "id" | ||
login = "login" | ||
age = "age" | ||
|
||
|
||
class UserSort(BaseSort): | ||
sort_by: Optional[UserSortByEnum] = None | ||
|
||
|
||
app = FastAPI() | ||
|
||
|
||
@app.get("/users") | ||
async def get_multiple_users( | ||
filter_: UserFilter = FilterDepends(UserFilter), | ||
pagination: OffsetPagination = PaginationDepends(OffsetPagination), | ||
sort: UserSort = SortDepends(UserSort), | ||
): | ||
... | ||
``` | ||
|
||
!!! Tip | ||
|
||
As of [`FastAPI>=0.115`](https://github.com/fastapi/fastapi/releases/tag/0.115.0), | ||
the [`PaginationDepends`][pydantic_filters.plugins.fastapi.PaginationDepends] and | ||
[`SortDepends`][pydantic_filters.plugins.fastapi.SortDepends] functions can be replaced by | ||
`Annotated[PaginationOrSortSchema, fastapi.Query()]`. | ||
|
||
![fastapi-not-so-simple-example.png](../images/fastapi-not-so-simple-example.png) |
Oops, something went wrong.