Skip to content

Commit

Permalink
feat: add advanced filtering on GET /prices (#29)
Browse files Browse the repository at this point in the history
* Add fastapi-filter package

* Replace existing filters with new library
  • Loading branch information
raphodn authored Nov 15, 2023
1 parent 4e39b71 commit 9b52406
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 23 deletions.
14 changes: 2 additions & 12 deletions app/api.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import asyncio
import uuid
from datetime import date
from pathlib import Path
from typing import Annotated

Expand All @@ -9,7 +8,6 @@
Depends,
FastAPI,
HTTPException,
Query,
Request,
Response,
UploadFile,
Expand All @@ -18,6 +16,7 @@
from fastapi.responses import HTMLResponse, PlainTextResponse
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from fastapi.templating import Jinja2Templates
from fastapi_filter import FilterDepends
from fastapi_pagination import Page, add_pagination
from fastapi_pagination.ext.sqlalchemy import paginate
from openfoodfacts.utils import get_logger
Expand Down Expand Up @@ -133,16 +132,7 @@ async def authentication(


@app.get("/prices", response_model=Page[schemas.PriceBase])
async def get_price(
product_code: str | None = None,
location_osm_id: int | None = None,
date: date | None = None,
):
filters = {
"product_code": product_code,
"location_osm_id": location_osm_id,
"date": date,
}
async def get_price(filters: schemas.PriceFilter = FilterDepends(schemas.PriceFilter)):
return paginate(db, crud.get_prices_query(filters=filters))


Expand Down
13 changes: 4 additions & 9 deletions app/crud.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

from app import config
from app.models import Price, Proof, User
from app.schemas import PriceCreate, ProofBase, UserBase
from app.schemas import PriceCreate, PriceFilter, UserBase


def get_user(db: Session, user_id: str):
Expand Down Expand Up @@ -56,20 +56,15 @@ def delete_user(db: Session, user_id: UserBase):
return False


def get_prices_query(filters: dict | None = None):
def get_prices_query(filters: PriceFilter | None = None):
"""Useful for pagination."""
query = select(Price)
if filters:
if filters.get("product_code", None):
query = query.filter(Price.product_code == filters["product_code"])
if filters.get("location_osm_id", None):
query = query.filter(Price.location_osm_id == filters["location_osm_id"])
if filters.get("date", None):
query = query.filter(Price.date == filters["date"])
query = filters.filter(query)
return query


def get_prices(db: Session, filters: dict | None = None):
def get_prices(db: Session, filters: PriceFilter | None = None):
return db.execute(get_prices_query(filters=filters)).all()


Expand Down
23 changes: 23 additions & 0 deletions app/schemas.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
from datetime import date, datetime
from typing import Optional

from fastapi_filter.contrib.sqlalchemy import Filter
from pydantic import BaseModel, ConfigDict, Field, field_serializer, field_validator
from sqlalchemy_utils import Currency

from app.enums import PriceLocationOSMType
from app.models import Price


class UserBase(BaseModel):
Expand Down Expand Up @@ -54,3 +57,23 @@ class ProofBase(ProofCreate):
id: int
owner: str
created: datetime


class PriceFilter(Filter):
product_code: Optional[str] | None = None
location_osm_id: Optional[int] | None = None
location_osm_type: Optional[PriceLocationOSMType] | None = None
price: Optional[int] | None = None
currency: Optional[str] | None = None
price__gt: Optional[int] | None = None
price__gte: Optional[int] | None = None
price__lt: Optional[int] | None = None
price__lte: Optional[int] | None = None
date: Optional[str] | None = None
date__gt: Optional[str] | None = None
date__gte: Optional[str] | None = None
date__lt: Optional[str] | None = None
date__lte: Optional[str] | None = None

class Constants(Filter.Constants):
model = Price
22 changes: 21 additions & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ sqlalchemy = "~2.0.23"
sqlalchemy-utils = "~0.41.1"
uvicorn = "~0.23.2"
fastapi-pagination = "^0.12.12"
fastapi-filter = "^1.0.0"


[tool.poetry.group.dev.dependencies]
Expand All @@ -44,5 +45,8 @@ exclude = '''
)/
'''

[tool.isort]
profile = "black"

[tool.mypy]
ignore_missing_imports = true
ignore_missing_imports = true

0 comments on commit 9b52406

Please sign in to comment.