Skip to main content

FastAPI integration for Refine simple-rest data provider

Project description

fastapi-refine

PyPI version Python Versions License: MIT

FastAPI integration for Refine simple-rest data provider. Build type-safe, production-ready REST APIs that work seamlessly with Refine's data provider conventions.

Features

  • Automatic Query Parsing: Parse Refine's filter, sort, and pagination parameters out-of-the-box
  • Type-Safe: Full type hints and mypy strict mode compliance
  • SQLModel Integration: First-class support for SQLModel/SQLAlchemy ORM
  • CRUD Router Factory: Generate complete CRUD endpoints with one class
  • Flexible Filtering: Support for eq, ne, gte, lte, like operators and full-text search
  • Hook System: Inject custom logic before/after operations (permissions, validation, etc.)
  • Production Ready: Built with FastAPI best practices

Installation

pip install fastapi-refine

Quick Start

Basic Usage with Manual Endpoints

from typing import Annotated

from fastapi import APIRouter, Depends
from sqlmodel import Session, select
from fastapi_refine import (
    FilterConfig,
    FilterField,
    SortConfig,
    RefineQuery,
    RefineResponse,
    refine_query,
    refine_response,
)
from fastapi_refine.core import parse_bool

from .models import Item, ItemPublic
from .database import get_session

router = APIRouter(prefix="/items", tags=["items"])

SessionDep = Annotated[Session, Depends(get_session)]

# Configure which fields can be filtered and sorted
filter_config = FilterConfig(
    fields={
        "id": FilterField(Item.id, str),
        "title": FilterField(Item.title, str),
        "is_active": FilterField(Item.is_active, parse_bool),
    },
    search_fields=[Item.title, Item.description],  # Full-text search fields
)

sort_config = SortConfig(
    fields={
        "id": Item.id,
        "title": Item.title,
        "created_at": Item.created_at,
    }
)

@router.get("/", response_model=list[ItemPublic])
def read_items(
    session: SessionDep,
    refine_resp: Annotated[RefineResponse, Depends(refine_response())],
    query: Annotated[RefineQuery, Depends(refine_query(Item, filter_config, sort_config))],
) -> list[ItemPublic]:
    # query.conditions contains parsed WHERE clauses
    # query.order_by contains ORDER BY clauses
    # query.offset and query.limit are ready for pagination

    items = session.exec(
        select(Item)
        .where(*query.conditions)
        .order_by(*query.order_by)
        .offset(query.offset)
        .limit(query.limit)
    ).all()

    # Set x-total-count header for Refine pagination
    total = query.get_count(session, query.conditions)
    refine_resp.set_total_count(total)

    return items

Automatic CRUD Router (Recommended)

Generate all CRUD endpoints automatically:

from fastapi import FastAPI
from fastapi_refine import RefineCRUDRouter, FilterConfig, FilterField, SortConfig
from fastapi_refine.core import parse_bool
from .models import Item, ItemCreate, ItemUpdate, ItemPublic
from .database import get_session

app = FastAPI()

# Create router with full CRUD operations
crud_router = RefineCRUDRouter(
    model=Item,
    prefix="/items",
    create_schema=ItemCreate,
    update_schema=ItemUpdate,
    public_schema=ItemPublic,
    session_dep=get_session,
    filter_config=FilterConfig(
        fields={
            "title": FilterField(Item.title, str),
            "is_active": FilterField(Item.is_active, parse_bool),
        },
        search_fields=[Item.title],
    ),
    sort_config=SortConfig(
        fields={"title": Item.title, "created_at": Item.created_at}
    ),
    tags=["items"],
)

app.include_router(crud_router.router)

This automatically creates:

  • GET /items/ - List with filtering, sorting, pagination
  • GET /items/{id} - Get single item
  • POST /items/ - Create item
  • PATCH /items/{id} - Update item
  • DELETE /items/{id} - Delete item

Advanced Usage

Custom Hooks for Permissions

from fastapi import Depends, HTTPException
from fastapi_refine import RefineHooks, HookContext, RefineCRUDRouter

def before_query(context: HookContext, conditions: list) -> list:
    """Filter items to only show user's own items"""
    if context.current_user:
        conditions.append(context.model.owner_id == context.current_user.id)
    return conditions

def before_delete(context: HookContext, item) -> None:
    """Only allow deleting own items"""
    if item.owner_id != context.current_user.id:
        raise HTTPException(status_code=403, detail="Not authorized")

hooks = RefineHooks(
    before_query=before_query,
    before_delete=before_delete,
)

crud_router = RefineCRUDRouter(
    model=Item,
    hooks=hooks,
    current_user_dep=get_current_user,
    # ... other config
)

Pagination Configuration

from fastapi_refine import PaginationConfig, RefineCRUDRouter

pagination_config = PaginationConfig(
    default_start=0,
    default_page_size=50,
    max_page_size=500,  # Prevent excessive queries
)

crud_router = RefineCRUDRouter(
    pagination_config=pagination_config,
    # ... other config
)

Supported Query Parameters

The library parses Refine simple-rest query parameters:

Filtering

  • field=value - Exact match (eq)
  • field_ne=value - Not equal
  • field_gte=value - Greater than or equal
  • field_lte=value - Less than or equal
  • field_like=value - Contains (case-insensitive)
  • q=search - Full-text search across configured fields

Sorting

  • _sort=field1,field2 - Sort by multiple fields
  • _order=asc,desc - Sort order for each field

Pagination

  • Range-based: _start=0&_end=20
  • Legacy skip/limit is rejected with 422 in 0.2.x (planned to be silently ignored after 0.5.x).

Example Query

GET /items?title_like=hello&is_active=true&_sort=created_at&_order=desc&_start=0&_end=10

Type Converters

Built-in converters for common types:

from fastapi_refine import FilterConfig, FilterField
from fastapi_refine.core import parse_bool, parse_uuid

filter_config = FilterConfig(
    fields={
        "id": FilterField(Item.id, parse_uuid),
        "is_active": FilterField(Item.is_active, parse_bool),
        "price": FilterField(Item.price, float),
        "quantity": FilterField(Item.quantity, int),
    }
)

Requirements

  • Python 3.10+
  • FastAPI 0.114.2+
  • SQLModel 0.0.21+

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

MIT License - see LICENSE file for details.

Links

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fastapi_refine-0.2.0.tar.gz (18.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

fastapi_refine-0.2.0-py3-none-any.whl (16.9 kB view details)

Uploaded Python 3

File details

Details for the file fastapi_refine-0.2.0.tar.gz.

File metadata

  • Download URL: fastapi_refine-0.2.0.tar.gz
  • Upload date:
  • Size: 18.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for fastapi_refine-0.2.0.tar.gz
Algorithm Hash digest
SHA256 a1ccfd69bbdaafa7311644e795fcbe6ec254871b94d545b07381c643f1187780
MD5 931f78c9f97bd189ccce0e4e3759fb8c
BLAKE2b-256 ee5912f5a3865cce9580b6b1fbb0b9a47c3f08ea374bc7e90a5f06181a2f8936

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastapi_refine-0.2.0.tar.gz:

Publisher: publish.yml on koch3092/fastapi-refine

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fastapi_refine-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: fastapi_refine-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 16.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for fastapi_refine-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8c86a6eab7dd75481c9833e1789de361a6bdabac2093b43985ba6e295c85fd0d
MD5 19bef307ff8a825f6f24d9ce592a90cf
BLAKE2b-256 8330417c3ea6fbf3da4da2576b2948f4363ae7d96100f1838e261d80c1e9aacb

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastapi_refine-0.2.0-py3-none-any.whl:

Publisher: publish.yml on koch3092/fastapi-refine

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page