{"id":19977740,"url":"https://github.com/boardpack/filterify","last_synced_at":"2025-03-01T19:14:55.064Z","repository":{"id":63915498,"uuid":"542760342","full_name":"boardpack/filterify","owner":"boardpack","description":"filterify is a pydantic-based library to handle filters from the query params","archived":false,"fork":false,"pushed_at":"2023-05-29T17:06:22.000Z","size":123,"stargazers_count":0,"open_issues_count":6,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-01-12T10:10:07.206Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://filterify.boardpack.org","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/boardpack.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"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":"2022-09-28T19:30:43.000Z","updated_at":"2022-11-28T22:09:49.000Z","dependencies_parsed_at":"2024-11-13T03:29:41.978Z","dependency_job_id":"41b7a1de-a66a-4be6-847c-abb539b3d74f","html_url":"https://github.com/boardpack/filterify","commit_stats":{"total_commits":51,"total_committers":3,"mean_commits":17.0,"dds":0.5686274509803921,"last_synced_commit":"acc1abd874e4c4e274cf8f0d2ecb5fcd5e18fd62"},"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boardpack%2Ffilterify","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boardpack%2Ffilterify/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boardpack%2Ffilterify/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boardpack%2Ffilterify/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/boardpack","download_url":"https://codeload.github.com/boardpack/filterify/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241411542,"owners_count":19958753,"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":[],"created_at":"2024-11-13T03:29:07.506Z","updated_at":"2025-03-01T19:14:55.044Z","avatar_url":"https://github.com/boardpack.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://filterify.boardpack.org/\"\u003e\u003cimg src=\"https://filterify.boardpack.org/img/logo-white.png\" alt=\"Filterify\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n    \u003cem\u003efilterify is a pydantic-based library to handle filters from the query params.\u003c/em\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://github.com/boardpack/filterify/actions?query=workflow%3ATest\" target=\"_blank\"\u003e\n        \u003cimg src=\"https://github.com/boardpack/filterify/workflows/Test/badge.svg\" alt=\"Test\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://codecov.io/gh/boardpack/filterify\" target=\"_blank\"\u003e\n        \u003cimg src=\"https://img.shields.io/codecov/c/github/boardpack/filterify?color=%2334D058\" alt=\"Coverage\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://pypi.org/project/filterify\" target=\"_blank\"\u003e\n        \u003cimg src=\"https://img.shields.io/pypi/v/filterify?color=%2334D058\u0026label=pypi%20package\" alt=\"Package version\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://github.com/psf/black\"\u003e\u003cimg alt=\"Code style: black\" src=\"https://camo.githubusercontent.com/d91ed7ac7abbd5a6102cbe988dd8e9ac21bde0a73d97be7603b891ad08ce3479/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f636f64652532307374796c652d626c61636b2d3030303030302e737667\" data-canonical-src=\"https://img.shields.io/badge/code%20style-black-000000.svg\" style=\"max-width:100%;\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://pycqa.github.io/isort/\" rel=\"nofollow\"\u003e\u003cimg src=\"https://camo.githubusercontent.com/fe4a658dd745f746410f961ae45d44355db1cc0e4c09c7877d265c1380248943/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f253230696d706f7274732d69736f72742d2532333136373462313f7374796c653d666c6174266c6162656c436f6c6f723d656638333336\" alt=\"Imports: isort\" data-canonical-src=\"https://img.shields.io/badge/%20imports-isort-%231674b1?style=flat\u0026amp;labelColor=ef8336\" style=\"max-width:100%;\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n---\n\n**Documentation**: \u003ca href=\"https://filterify.boardpack.org\" target=\"_blank\"\u003ehttps://filterify.boardpack.org\u003c/a\u003e\n\n**Source Code**: \u003ca href=\"https://github.com/boardpack/filterify\" target=\"_blank\"\u003ehttps://github.com/boardpack/filterify\u003c/a\u003e\n\n---\n\n## Requirements\n\nPython 3.8+\n\nfilterify has the next dependencies:\n\n* \u003ca href=\"https://pydantic-docs.helpmanual.io/\" class=\"external-link\" target=\"_blank\"\u003ePydantic\u003c/a\u003e\n\n## Installation\n\n\u003cdiv class=\"termy\"\u003e\n\n```console\n$ pip install filterify\n\n---\u003e 100%\n```\n\n\u003c/div\u003e\n\n## First steps\n\nTo start to work with filterify, you just need to have some Pydantic model you want to have as filters.\n\nLet's define simple `Address` and `Shipment` models. Then just pass the `Shipment` model to the `Filterify` constructor\nand you will get a callable object to parse query params. By default, the parser returns a dictionary structure with\nthe parsing results.\n\n```Python  hl_lines=\"18 20\"\nfrom pydantic import BaseModel\nfrom filterify import Filterify\n\n\nclass Address(BaseModel):\n    street: str\n    city: str\n    country: str\n\n\nclass Shipment(BaseModel):\n    name: str\n    sender: Address\n    recipient: Address\n    weight: float\n\n\nmodel_filter = Filterify(Shipment)\n\nprint(model_filter('name=shoes\u0026sender__country=US\u0026recipient__country__ne=CA'))\n# [\n#     {\n#         'field': [\n#             'name'\n#         ],\n#         'value': 'shoes',\n#         'operation': 'eq'\n#     },\n#     {\n#         'field': [\n#             'sender',\n#             'country'\n#         ],\n#         'value': 'US',\n#         'operation': 'eq'\n#     },\n#     {\n#         'field': [\n#             'recipient',\n#             'country'\n#         ],\n#         'value': 'CA',\n#         'operation': 'ne'\n#     }\n# ]\n\n```\n_(This script is complete, it should run \"as is\")_\n\nFilterify supports nested models and uses `__` as a delimiter for the nested models and operations. If you want to\nchange it, pass the needed `delimiter` to the constructor as it's shown in the next example.\n\n```Python  hl_lines=\"13\"\nfrom pydantic import BaseModel\nfrom filterify import Filterify\n\n\nclass Address(BaseModel):\n    country: str\n\n\nclass Shipment(BaseModel):\n    sender: Address\n\n\nmodel_filter = Filterify(Shipment, delimiter='$')\n\nprint(model_filter('sender$country$ne=US'))\n# [\n#     {\n#         'field': [\n#             'sender',\n#             'country'\n#         ],\n#         'value': 'US',\n#         'operation': 'ne'\n#     }\n# ]\n\n```\n_(This script is complete, it should run \"as is\")_\n\nAlso, by default unknown fields are ignored, but you can change this behavior by passing `False` to the constructor\nparameter `ignore_unknown_name`.\n\n```Python  hl_lines=\"9\"\nfrom pydantic import BaseModel\nfrom filterify import Filterify\n\n\nclass User(BaseModel):\n    name: str\n\n\nmodel_filter = Filterify(User, ignore_unknown_name=False)\n\nprint(model_filter('sender=US'))\n# filterify.exceptions.UnknownFieldError: Filter name is not presented in the model: sender\n\n```\n_(This script is complete, it should run \"as is\")_\n\n## Supported types\n\nCurrently, filterify supports a small number of types, it will be extended in the future:\n\n| Field type | Available lookups                      |\n|------------|----------------------------------------|\n| str        | `eq`, `ne`, `contains`, `not_contains` |\n| int        | `eq`, `ne`, `gt`, `lt`, `gte`, `lte`   |\n| float      | `eq`, `ne`, `gt`, `lt`, `gte`, `lte`   |\n| bool       | `eq`, `ne`                             |\n| list       | `eq`, `ne`                             |\n\nIn the case of an unknown type or lookup, it will be raised `UnknownTypeError` and `UnknownOperationError` exceptions.\n\n## Ordering option\n\nYou can add an `ordering` field that accepts all model field names. Currently, it's used a django-like style when desc\nis passed as `-field_name`.\n\n```Python  hl_lines=\"14\"\nfrom pydantic import BaseModel\nfrom filterify import Filterify\n\n\nclass Address(BaseModel):\n    country: str\n\n\nclass Shipment(BaseModel):\n    name: str\n    sender: Address\n\n\nmodel_filter = Filterify(Shipment, ordering=True)\n\nprint(model_filter('ordering=unknown_field'))\n# raises standard pydantic ValidationError with the next message:\n# unexpected value; permitted: 'name', '-name', 'sender__country', '-sender__country'\n\n```\n_(This script is complete, it should run \"as is\")_\n\nIf you want to change the accepted field name list, you can pass a list instead of the `True` value.\n\n```Python  hl_lines=\"14\"\nfrom pydantic import BaseModel\nfrom filterify import Filterify\n\n\nclass Address(BaseModel):\n    country: str\n\n\nclass Shipment(BaseModel):\n    name: str\n    sender: Address\n\n\nmodel_filter = Filterify(Shipment, ordering=['name'])\n\nprint(model_filter('ordering=unknown_field'))\n# raises standard pydantic ValidationError with the next message:\n# unexpected value; permitted: 'name', '-name'\n\n```\n_(This script is complete, it should run \"as is\")_\n\n## Usage with FastAPI\n\nMost validation work is done by pydantic, so filterify can be easily used with FastAPI.\nThe internal validation model is wrapped by `fastapi.Depends` and exposed by the `as_dependency` method.\n\n```Python  hl_lines=\"29 35\"\nimport uvicorn\nfrom fastapi import FastAPI\nfrom pydantic import BaseModel\n\nfrom filterify import Filterify\n\n\nclass Address(BaseModel):\n    street: str\n    city: str\n    country: str\n\n\nclass Shipment(BaseModel):\n    name: str\n    sender: Address\n    recipient: Address\n    weight: float\n    length: float\n    height: float\n\n\nshipment_filter = Filterify(Shipment)\n\n\napp = FastAPI()\n\n\n@app.get('/shipments', dependencies=[shipment_filter.as_dependency()])\ndef shipments():\n    return []\n\n\n@app.get('/another_shipments')\ndef another_shipments(filters=shipment_filter.as_dependency()):\n    print(filters)\n    return []\n\n\nif __name__ == '__main__':\n    uvicorn.run(app)\n\n```\n_(This script is complete, it should run \"as is\")_\n\n## Acknowledgments\n\nSpecial thanks to [Sebastián Ramírez](https://github.com/tiangolo) and his [FastAPI](https://github.com/tiangolo/fastapi) project,  some scripts and documentation structure and parts were used from there.\n\n## License\n\nThis project is licensed under the terms of the MIT license.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fboardpack%2Ffilterify","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fboardpack%2Ffilterify","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fboardpack%2Ffilterify/lists"}