Name | fastapi-qengine JSON |
Version |
0.2.0
JSON |
| download |
home_page | None |
Summary | fastapi-qengine is an advanced query engine for FastAPI, inspired by Loopback 4's filtering system. It allows building complex queries directly from URLs with a flexible syntax. |
upload_time | 2025-08-28 22:28:01 |
maintainer | None |
docs_url | None |
author | None |
requires_python | >=3.9 |
license | None |
keywords |
fastapi
beanie
mongodb
query
filter
engine
|
VCS |
|
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
# fastapi-qengine
[](https://badge.fury.io/py/fastapi-qengine)
[](https://opensource.org/licenses/MIT)
Un motor de consultas avanzado para FastAPI, inspirado en el poderoso sistema de filtros de Loopback 4. Diseñado inicialmente para Beanie/PyMongo, con planes de expansión a otros ORMs en el futuro.
`fastapi-qengine` te permite construir consultas complejas para tus modelos directamente desde la URL con una sintaxis flexible, ofreciendo una alternativa más potente y con menos configuración que `fastapi-filter`.
## Motivación
Mientras que librerías como `fastapi-filter` son excelentes, a menudo requieren una configuración detallada por cada modelo y campo. `fastapi-qengine` trae la flexibilidad del sistema de filtros de Loopback 4 al ecosistema de FastAPI, permitiendo a los clientes construir consultas complejas con operadores lógicos, selección de campos y ordenamiento desde la URL.
Este proyecto se enfoca únicamente en la **creación de la consulta**, delegando la paginación a librerías especializadas como [fastapi-pagination](https://github.com/uriyyo/fastapi-pagination).
## Características
- **Sintaxis de filtro flexible:** Soporte para JSON anidado en los parámetros de la URL y para JSON completo en formato string.
- **Operadores de consulta avanzados:** Soporte para operadores como `$gt`, `$gte`, `$in`, `$nin`, `$lt`, `$lte`, `$ne`, y más.
- **Combinaciones lógicas:** Soporte completo para consultas `$and` y `$or`.
- **Selección de campos (Proyección):** Elige qué campos devolver en los resultados con `fields`.
- **Ordenamiento dinámico:** Ordena los resultados con `order`.
- **Integración mínima:** Diseñado para funcionar con Beanie y FastAPI con una configuración mínima.
- **Enfocado en consultas:** No se encarga de la paginación, permitiendo la integración con librerías dedicadas.
## Instalación
```bash
pip install fastapi-qengine
pip install fastapi-pagination # Recomendado para la paginación
```
## Ejemplo Rápido
### 1. Define tu modelo Beanie
```python
# main.py
from beanie import Document
from pymongo import AsyncMongoClient
class Product(Document):
name: str
category: str
price: float
in_stock: bool
class Settings:
name = "products"
async def init_db():
client = AsyncMongoClient("mongodb://localhost:27017")
await Document.init_all(database=client.db_name, documents=[Product])
```
### 2. Crea tu endpoint de FastAPI
```python
# main.py
from fastapi import FastAPI, Depends
from fastapi_pagination import Page, add_pagination
from fastapi_pagination.ext.beanie import apaginate
from contextlib import asynccontextmanager
from fastapi_qengine import create_qe_dependency
from fastapi_qengine.backends.beanie import BeanieQueryEngine
app = FastAPI()
@asynccontextmanager
async def lifespan(app: FastAPI):
# Startup
await init_db()
yield
app = FastAPI(lifespan=lifespan)
# Engine explícito por backend
beanie_engine = BeanieQueryEngine(Product)
qe_dep = create_qe_dependency(beanie_engine)
@app.get("/products", response_model=Page[Product])
async def get_products(q = Depends(qe_dep)):
# q es una tupla (query, projection_model, sort) lista para apaginate
query, projection_model, sort = q
return await apaginate(query, projection_model=projection_model, sort=sort)
add_pagination(app)
```
### 3. Realiza consultas desde la URL
`fastapi-qengine` soporta dos formatos para pasar el filtro, dándote flexibilidad según la complejidad de la consulta.
#### Formato 1: Parámetros de URL anidados (Ideal para consultas simples)
Para consultas directas o para usar desde un navegador, puedes usar la sintaxis de corchetes. Es más legible para filtros sencillos.
* **Buscar productos con un precio mayor a 50:**
`/products?filter[where][price][$gt]=50`
* **Buscar productos en stock de la categoría "electronics":**
`/products?filter[where][category]=electronics&filter[where][in_stock]=true`
* **Buscar productos y ordenarlos por precio (descendente):**
`/products?filter[where][in_stock]=true&filter[order]=-price`
#### Formato 2: Stringified JSON (Recomendado para consultas complejas)
Para consultas que involucran operadores lógicos como `$or`, `$and` o estructuras anidadas complejas, el formato de JSON como string es la mejor opción. Recuerda codificar el JSON para la URL.
* **Buscar productos en la categoría "electronics" O que cuesten menos de 20:**
* **JSON Filter:** `{"where": {"$or": [{"category": "electronics"}, {"price": {"$lt": 20}}]}}`
* **URL Codificada:** `/products?filter=%7B%22where%22%3A%20%7B%22%24or%22%3A%20%5B%7B%22category%22%3A%20%22electronics%22%7D%2C%20%7B%22price%22%3A%20%7B%22%24lt%22%3A%2020%7D%7D%5D%7D%7D`
## Sintaxis de Filtro Soportada
El objeto `filter` acepta las siguientes claves, inspiradas en la especificación de Loopback.
### `where`
Un objeto que define las condiciones de búsqueda. Utiliza la sintaxis de operadores de PyMongo.
- `{"where": {"category": "books"}}`
- `{"where": {"price": {"$gte": 10, "$lte": 50}}}`
- `{"where": {"category": {"$in": ["electronics", "appliances"]}}}`
- `{"where": {"$and": [{"in_stock": true}, {"price": {"$lt": 100}}]}}`
### `order`
Una cadena de texto para ordenar los resultados. Usa el prefijo `-` para orden descendente.
- `{"order": "price"}` (ascendente)
- `{"order": "-price"}` (descendente)
### `fields`
Un objeto para especificar qué campos incluir (proyección).
- `{"fields": {"name": 1, "price": 1}}` (incluye solo `name` y `price`)
## Comparación con otras librerías
#### vs `fastapi-filter`
`fastapi-filter` es una librería excelente, pero requiere definir clases de filtro para cada modelo. `fastapi-qengine` adopta un enfoque diferente al permitir que el cliente construya la consulta completa en un solo objeto JSON (o vía parámetros anidados), reduciendo la configuración en el backend.
#### vs `fastapi-querybuilder`
`fastapi-qengine` comparte el objetivo de `fastapi-querybuilder` de facilitar la creación de consultas complejas. La principal diferencia es que `fastapi-qengine` está diseñado específicamente para Beanie en su versión inicial y sigue de cerca la especificación de filtros de Loopback 4, una solución probada y robusta en el ecosistema de Node.js.
## Contribuciones
Las contribuciones son bienvenidas. Por favor, abre un issue o un pull request para discutir cualquier cambio.
### Desarrollo
Para contribuir al proyecto:
```bash
# Clonar el repositorio
git clone https://github.com/urielcuriel/fastapi-qengine.git
cd fastapi-qengine
# Instalar dependencias de desarrollo
uv pip install -e ".[dev]"
# Ejecutar tests
uv run pytest
# Ejecutar tests con cobertura
uv run pytest --cov=fastapi_qengine --cov-report=html
```
Ver [DEVELOPMENT.md](DEVELOPMENT.md) para más detalles sobre desarrollo y testing.
### Testing
El proyecto utiliza pytest para testing:
- **66 tests** cubriendo toda la funcionalidad
- **78% de cobertura** de código
- Tests unitarios, de integración y end-to-end
- Validación de seguridad y manejo de errores
```bash
# Ejecutar todos los tests
uv run pytest
# Tests específicos
uv run pytest tests/test_basic.py
uv run pytest -k "parser"
# Con cobertura detallada
uv run pytest --cov=fastapi_qengine --cov-report=html
```
## Licencia
Este proyecto está bajo la Licencia MIT.
Raw data
{
"_id": null,
"home_page": null,
"name": "fastapi-qengine",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.9",
"maintainer_email": null,
"keywords": "fastapi, beanie, mongodb, query, filter, engine",
"author": null,
"author_email": "Uriel Curiel <kratoz.00616@gmail.com>",
"download_url": "https://files.pythonhosted.org/packages/24/64/5351f097874422445c5bbd8e5c060ccb9010bff0287f146504778425f947/fastapi_qengine-0.2.0.tar.gz",
"platform": null,
"description": "# fastapi-qengine\r\n\r\n[](https://badge.fury.io/py/fastapi-qengine)\r\n[](https://opensource.org/licenses/MIT)\r\n\r\nUn motor de consultas avanzado para FastAPI, inspirado en el poderoso sistema de filtros de Loopback 4. Dise\u00f1ado inicialmente para Beanie/PyMongo, con planes de expansi\u00f3n a otros ORMs en el futuro.\r\n\r\n`fastapi-qengine` te permite construir consultas complejas para tus modelos directamente desde la URL con una sintaxis flexible, ofreciendo una alternativa m\u00e1s potente y con menos configuraci\u00f3n que `fastapi-filter`.\r\n\r\n## Motivaci\u00f3n\r\n\r\nMientras que librer\u00edas como `fastapi-filter` son excelentes, a menudo requieren una configuraci\u00f3n detallada por cada modelo y campo. `fastapi-qengine` trae la flexibilidad del sistema de filtros de Loopback 4 al ecosistema de FastAPI, permitiendo a los clientes construir consultas complejas con operadores l\u00f3gicos, selecci\u00f3n de campos y ordenamiento desde la URL.\r\n\r\nEste proyecto se enfoca \u00fanicamente en la **creaci\u00f3n de la consulta**, delegando la paginaci\u00f3n a librer\u00edas especializadas como [fastapi-pagination](https://github.com/uriyyo/fastapi-pagination).\r\n\r\n## Caracter\u00edsticas\r\n\r\n- **Sintaxis de filtro flexible:** Soporte para JSON anidado en los par\u00e1metros de la URL y para JSON completo en formato string.\r\n- **Operadores de consulta avanzados:** Soporte para operadores como `$gt`, `$gte`, `$in`, `$nin`, `$lt`, `$lte`, `$ne`, y m\u00e1s.\r\n- **Combinaciones l\u00f3gicas:** Soporte completo para consultas `$and` y `$or`.\r\n- **Selecci\u00f3n de campos (Proyecci\u00f3n):** Elige qu\u00e9 campos devolver en los resultados con `fields`.\r\n- **Ordenamiento din\u00e1mico:** Ordena los resultados con `order`.\r\n- **Integraci\u00f3n m\u00ednima:** Dise\u00f1ado para funcionar con Beanie y FastAPI con una configuraci\u00f3n m\u00ednima.\r\n- **Enfocado en consultas:** No se encarga de la paginaci\u00f3n, permitiendo la integraci\u00f3n con librer\u00edas dedicadas.\r\n\r\n## Instalaci\u00f3n\r\n\r\n```bash\r\npip install fastapi-qengine\r\npip install fastapi-pagination # Recomendado para la paginaci\u00f3n\r\n```\r\n\r\n## Ejemplo R\u00e1pido\r\n\r\n### 1. Define tu modelo Beanie\r\n\r\n```python\r\n# main.py\r\nfrom beanie import Document\r\nfrom pymongo import AsyncMongoClient\r\n\r\nclass Product(Document):\r\n name: str\r\n category: str\r\n price: float\r\n in_stock: bool\r\n\r\n class Settings:\r\n name = \"products\"\r\n\r\nasync def init_db():\r\n client = AsyncMongoClient(\"mongodb://localhost:27017\")\r\n await Document.init_all(database=client.db_name, documents=[Product])\r\n```\r\n\r\n### 2. Crea tu endpoint de FastAPI\r\n\r\n```python\r\n# main.py\r\nfrom fastapi import FastAPI, Depends\r\nfrom fastapi_pagination import Page, add_pagination\r\nfrom fastapi_pagination.ext.beanie import apaginate\r\nfrom contextlib import asynccontextmanager\r\n\r\nfrom fastapi_qengine import create_qe_dependency\r\nfrom fastapi_qengine.backends.beanie import BeanieQueryEngine\r\n\r\napp = FastAPI()\r\n\r\n\r\n@asynccontextmanager\r\nasync def lifespan(app: FastAPI):\r\n # Startup\r\n await init_db()\r\n yield\r\n\r\napp = FastAPI(lifespan=lifespan)\r\n\r\n# Engine expl\u00edcito por backend\r\nbeanie_engine = BeanieQueryEngine(Product)\r\nqe_dep = create_qe_dependency(beanie_engine)\r\n\r\n@app.get(\"/products\", response_model=Page[Product])\r\nasync def get_products(q = Depends(qe_dep)):\r\n # q es una tupla (query, projection_model, sort) lista para apaginate\r\n query, projection_model, sort = q\r\n return await apaginate(query, projection_model=projection_model, sort=sort)\r\n\r\nadd_pagination(app)\r\n```\r\n\r\n### 3. Realiza consultas desde la URL\r\n\r\n`fastapi-qengine` soporta dos formatos para pasar el filtro, d\u00e1ndote flexibilidad seg\u00fan la complejidad de la consulta.\r\n\r\n#### Formato 1: Par\u00e1metros de URL anidados (Ideal para consultas simples)\r\n\r\nPara consultas directas o para usar desde un navegador, puedes usar la sintaxis de corchetes. Es m\u00e1s legible para filtros sencillos.\r\n\r\n* **Buscar productos con un precio mayor a 50:**\r\n `/products?filter[where][price][$gt]=50`\r\n\r\n* **Buscar productos en stock de la categor\u00eda \"electronics\":**\r\n `/products?filter[where][category]=electronics&filter[where][in_stock]=true`\r\n\r\n* **Buscar productos y ordenarlos por precio (descendente):**\r\n `/products?filter[where][in_stock]=true&filter[order]=-price`\r\n\r\n#### Formato 2: Stringified JSON (Recomendado para consultas complejas)\r\n\r\nPara consultas que involucran operadores l\u00f3gicos como `$or`, `$and` o estructuras anidadas complejas, el formato de JSON como string es la mejor opci\u00f3n. Recuerda codificar el JSON para la URL.\r\n\r\n* **Buscar productos en la categor\u00eda \"electronics\" O que cuesten menos de 20:**\r\n * **JSON Filter:** `{\"where\": {\"$or\": [{\"category\": \"electronics\"}, {\"price\": {\"$lt\": 20}}]}}`\r\n * **URL Codificada:** `/products?filter=%7B%22where%22%3A%20%7B%22%24or%22%3A%20%5B%7B%22category%22%3A%20%22electronics%22%7D%2C%20%7B%22price%22%3A%20%7B%22%24lt%22%3A%2020%7D%7D%5D%7D%7D`\r\n\r\n## Sintaxis de Filtro Soportada\r\n\r\nEl objeto `filter` acepta las siguientes claves, inspiradas en la especificaci\u00f3n de Loopback.\r\n\r\n### `where`\r\n\r\nUn objeto que define las condiciones de b\u00fasqueda. Utiliza la sintaxis de operadores de PyMongo.\r\n\r\n- `{\"where\": {\"category\": \"books\"}}`\r\n- `{\"where\": {\"price\": {\"$gte\": 10, \"$lte\": 50}}}`\r\n- `{\"where\": {\"category\": {\"$in\": [\"electronics\", \"appliances\"]}}}`\r\n- `{\"where\": {\"$and\": [{\"in_stock\": true}, {\"price\": {\"$lt\": 100}}]}}`\r\n\r\n### `order`\r\n\r\nUna cadena de texto para ordenar los resultados. Usa el prefijo `-` para orden descendente.\r\n\r\n- `{\"order\": \"price\"}` (ascendente)\r\n- `{\"order\": \"-price\"}` (descendente)\r\n\r\n### `fields`\r\n\r\nUn objeto para especificar qu\u00e9 campos incluir (proyecci\u00f3n).\r\n\r\n- `{\"fields\": {\"name\": 1, \"price\": 1}}` (incluye solo `name` y `price`)\r\n\r\n## Comparaci\u00f3n con otras librer\u00edas\r\n\r\n#### vs `fastapi-filter`\r\n\r\n`fastapi-filter` es una librer\u00eda excelente, pero requiere definir clases de filtro para cada modelo. `fastapi-qengine` adopta un enfoque diferente al permitir que el cliente construya la consulta completa en un solo objeto JSON (o v\u00eda par\u00e1metros anidados), reduciendo la configuraci\u00f3n en el backend.\r\n\r\n#### vs `fastapi-querybuilder`\r\n\r\n`fastapi-qengine` comparte el objetivo de `fastapi-querybuilder` de facilitar la creaci\u00f3n de consultas complejas. La principal diferencia es que `fastapi-qengine` est\u00e1 dise\u00f1ado espec\u00edficamente para Beanie en su versi\u00f3n inicial y sigue de cerca la especificaci\u00f3n de filtros de Loopback 4, una soluci\u00f3n probada y robusta en el ecosistema de Node.js.\r\n\r\n## Contribuciones\r\n\r\nLas contribuciones son bienvenidas. Por favor, abre un issue o un pull request para discutir cualquier cambio.\r\n\r\n### Desarrollo\r\n\r\nPara contribuir al proyecto:\r\n\r\n```bash\r\n# Clonar el repositorio\r\ngit clone https://github.com/urielcuriel/fastapi-qengine.git\r\ncd fastapi-qengine\r\n\r\n# Instalar dependencias de desarrollo\r\nuv pip install -e \".[dev]\"\r\n\r\n# Ejecutar tests\r\nuv run pytest\r\n\r\n# Ejecutar tests con cobertura\r\nuv run pytest --cov=fastapi_qengine --cov-report=html\r\n```\r\n\r\nVer [DEVELOPMENT.md](DEVELOPMENT.md) para m\u00e1s detalles sobre desarrollo y testing.\r\n\r\n### Testing\r\n\r\nEl proyecto utiliza pytest para testing:\r\n\r\n- **66 tests** cubriendo toda la funcionalidad\r\n- **78% de cobertura** de c\u00f3digo\r\n- Tests unitarios, de integraci\u00f3n y end-to-end\r\n- Validaci\u00f3n de seguridad y manejo de errores\r\n\r\n```bash\r\n# Ejecutar todos los tests\r\nuv run pytest\r\n\r\n# Tests espec\u00edficos\r\nuv run pytest tests/test_basic.py\r\nuv run pytest -k \"parser\"\r\n\r\n# Con cobertura detallada\r\nuv run pytest --cov=fastapi_qengine --cov-report=html\r\n```\r\n\r\n## Licencia\r\n\r\nEste proyecto est\u00e1 bajo la Licencia MIT.\r\n",
"bugtrack_url": null,
"license": null,
"summary": "fastapi-qengine is an advanced query engine for FastAPI, inspired by Loopback 4's filtering system. It allows building complex queries directly from URLs with a flexible syntax.",
"version": "0.2.0",
"project_urls": null,
"split_keywords": [
"fastapi",
" beanie",
" mongodb",
" query",
" filter",
" engine"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "d2b19912c8db2505de64d815952bb4fec713108d1a458a0a1ded71b44b366b4e",
"md5": "0e752035b83aacbfcc586509a5c2fa7c",
"sha256": "e329b34a995eee69d0eacb96e759ec5c39a53c4544f9308ddb13afdff0cca80f"
},
"downloads": -1,
"filename": "fastapi_qengine-0.2.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "0e752035b83aacbfcc586509a5c2fa7c",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.9",
"size": 35806,
"upload_time": "2025-08-28T22:28:00",
"upload_time_iso_8601": "2025-08-28T22:28:00.139843Z",
"url": "https://files.pythonhosted.org/packages/d2/b1/9912c8db2505de64d815952bb4fec713108d1a458a0a1ded71b44b366b4e/fastapi_qengine-0.2.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "24645351f097874422445c5bbd8e5c060ccb9010bff0287f146504778425f947",
"md5": "c5691d640c470e393580289923f69c15",
"sha256": "83d260cdfd01011ae6b9aa69405b0dc8935b42f6f13f05bdcce18d8efb1092b4"
},
"downloads": -1,
"filename": "fastapi_qengine-0.2.0.tar.gz",
"has_sig": false,
"md5_digest": "c5691d640c470e393580289923f69c15",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.9",
"size": 36591,
"upload_time": "2025-08-28T22:28:01",
"upload_time_iso_8601": "2025-08-28T22:28:01.513124Z",
"url": "https://files.pythonhosted.org/packages/24/64/5351f097874422445c5bbd8e5c060ccb9010bff0287f146504778425f947/fastapi_qengine-0.2.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-08-28 22:28:01",
"github": false,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"lcname": "fastapi-qengine"
}