mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-07-09 03:04:54 -04:00
feat: implemented "order by" API parameters for recipe, food, and unit queries (#1356)
* Added API params to order by different properties * fix for incorrect var name * removed invalid default order_by * implemented fallback for invalid user input
This commit is contained in:
parent
932f4a72df
commit
7541175b75
@ -56,7 +56,9 @@ class RepositoryGeneric(Generic[Schema, Model]):
|
|||||||
|
|
||||||
return {**dct, **kwargs}
|
return {**dct, **kwargs}
|
||||||
|
|
||||||
def get_all(self, limit: int = None, order_by: str = None, start=0, override=None) -> list[Schema]:
|
def get_all(
|
||||||
|
self, limit: int = None, order_by: str = None, order_descending: bool = True, start=0, override=None
|
||||||
|
) -> list[Schema]:
|
||||||
# sourcery skip: remove-unnecessary-cast
|
# sourcery skip: remove-unnecessary-cast
|
||||||
eff_schema = override or self.schema
|
eff_schema = override or self.schema
|
||||||
|
|
||||||
@ -65,10 +67,19 @@ class RepositoryGeneric(Generic[Schema, Model]):
|
|||||||
q = self._query().filter_by(**fltr)
|
q = self._query().filter_by(**fltr)
|
||||||
|
|
||||||
if order_by:
|
if order_by:
|
||||||
if order_attr := getattr(self.model, str(order_by)):
|
try:
|
||||||
|
order_attr = getattr(self.model, str(order_by))
|
||||||
|
if order_descending:
|
||||||
order_attr = order_attr.desc()
|
order_attr = order_attr.desc()
|
||||||
|
|
||||||
|
else:
|
||||||
|
order_attr = order_attr.asc()
|
||||||
|
|
||||||
q = q.order_by(order_attr)
|
q = q.order_by(order_attr)
|
||||||
|
|
||||||
|
except AttributeError:
|
||||||
|
self.logger.info(f'Attempted to sort by unknown sort property "{order_by}"; ignoring')
|
||||||
|
|
||||||
return [eff_schema.from_orm(x) for x in q.offset(start).limit(limit).all()]
|
return [eff_schema.from_orm(x) for x in q.offset(start).limit(limit).all()]
|
||||||
|
|
||||||
def multi_query(
|
def multi_query(
|
||||||
|
@ -90,7 +90,9 @@ class RepositoryRecipes(RepositoryGeneric[Recipe, RecipeModel]):
|
|||||||
override_schema=override_schema,
|
override_schema=override_schema,
|
||||||
)
|
)
|
||||||
|
|
||||||
def summary(self, group_id, start=0, limit=99999, load_foods=False) -> Any:
|
def summary(
|
||||||
|
self, group_id, start=0, limit=99999, load_foods=False, order_by="date_added", order_descending=True
|
||||||
|
) -> Any:
|
||||||
args = [
|
args = [
|
||||||
joinedload(RecipeModel.recipe_category),
|
joinedload(RecipeModel.recipe_category),
|
||||||
joinedload(RecipeModel.tags),
|
joinedload(RecipeModel.tags),
|
||||||
@ -100,11 +102,27 @@ class RepositoryRecipes(RepositoryGeneric[Recipe, RecipeModel]):
|
|||||||
if load_foods:
|
if load_foods:
|
||||||
args.append(joinedload(RecipeModel.recipe_ingredient).options(joinedload(RecipeIngredient.food)))
|
args.append(joinedload(RecipeModel.recipe_ingredient).options(joinedload(RecipeIngredient.food)))
|
||||||
|
|
||||||
|
try:
|
||||||
|
if order_by:
|
||||||
|
order_attr = getattr(RecipeModel, order_by)
|
||||||
|
else:
|
||||||
|
order_attr = RecipeModel.date_added
|
||||||
|
|
||||||
|
except AttributeError:
|
||||||
|
self.logger.info(f'Attempted to sort by unknown sort property "{order_by}"; ignoring')
|
||||||
|
order_attr = RecipeModel.date_added
|
||||||
|
|
||||||
|
if order_descending:
|
||||||
|
order_attr = order_attr.desc()
|
||||||
|
|
||||||
|
else:
|
||||||
|
order_attr = order_attr.asc()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
self.session.query(RecipeModel)
|
self.session.query(RecipeModel)
|
||||||
.options(*args)
|
.options(*args)
|
||||||
.filter(RecipeModel.group_id == group_id)
|
.filter(RecipeModel.group_id == group_id)
|
||||||
.order_by(RecipeModel.date_added.desc())
|
.order_by(order_attr)
|
||||||
.offset(start)
|
.offset(start)
|
||||||
.limit(limit)
|
.limit(limit)
|
||||||
.all()
|
.all()
|
||||||
|
@ -194,7 +194,14 @@ class RecipeController(BaseRecipeController):
|
|||||||
|
|
||||||
@router.get("", response_model=list[RecipeSummary])
|
@router.get("", response_model=list[RecipeSummary])
|
||||||
def get_all(self, q: RecipeGetAll = Depends(RecipeGetAll)):
|
def get_all(self, q: RecipeGetAll = Depends(RecipeGetAll)):
|
||||||
items = self.repo.summary(self.user.group_id, start=q.start, limit=q.limit, load_foods=q.load_food)
|
items = self.repo.summary(
|
||||||
|
self.user.group_id,
|
||||||
|
start=q.start,
|
||||||
|
limit=q.limit,
|
||||||
|
load_foods=q.load_food,
|
||||||
|
order_by=q.order_by,
|
||||||
|
order_descending=q.order_descending,
|
||||||
|
)
|
||||||
|
|
||||||
new_items = []
|
new_items = []
|
||||||
for item in items:
|
for item in items:
|
||||||
|
@ -39,7 +39,7 @@ class IngredientFoodsController(BaseUserController):
|
|||||||
|
|
||||||
@router.get("", response_model=list[IngredientFood])
|
@router.get("", response_model=list[IngredientFood])
|
||||||
def get_all(self, q: GetAll = Depends(GetAll)):
|
def get_all(self, q: GetAll = Depends(GetAll)):
|
||||||
return self.repo.get_all(start=q.start, limit=q.limit)
|
return self.repo.get_all(start=q.start, limit=q.limit, order_by=q.order_by, order_descending=q.order_descending)
|
||||||
|
|
||||||
@router.post("", response_model=IngredientFood, status_code=201)
|
@router.post("", response_model=IngredientFood, status_code=201)
|
||||||
def create_one(self, data: CreateIngredientFood):
|
def create_one(self, data: CreateIngredientFood):
|
||||||
|
@ -39,7 +39,7 @@ class IngredientUnitsController(BaseUserController):
|
|||||||
|
|
||||||
@router.get("", response_model=list[IngredientUnit])
|
@router.get("", response_model=list[IngredientUnit])
|
||||||
def get_all(self, q: GetAll = Depends(GetAll)):
|
def get_all(self, q: GetAll = Depends(GetAll)):
|
||||||
return self.repo.get_all(start=q.start, limit=q.limit)
|
return self.repo.get_all(start=q.start, limit=q.limit, order_by=q.order_by, order_descending=q.order_descending)
|
||||||
|
|
||||||
@router.post("", response_model=IngredientUnit, status_code=201)
|
@router.post("", response_model=IngredientUnit, status_code=201)
|
||||||
def create_one(self, data: CreateIngredientUnit):
|
def create_one(self, data: CreateIngredientUnit):
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
|
from typing import Optional
|
||||||
|
|
||||||
from mealie.schema._mealie import MealieModel
|
from mealie.schema._mealie import MealieModel
|
||||||
|
|
||||||
|
|
||||||
class GetAll(MealieModel):
|
class GetAll(MealieModel):
|
||||||
start: int = 0
|
start: int = 0
|
||||||
limit: int = 999
|
limit: int = 999
|
||||||
|
order_by: Optional[str]
|
||||||
|
order_descending: Optional[bool] = True
|
||||||
|
Loading…
x
Reference in New Issue
Block a user