feat: Query Filter Builder for Cookbooks and Meal Plans (#4346)

This commit is contained in:
Michael Genson
2024-10-17 10:35:39 -05:00
committed by GitHub
parent 2a9a6fa5e6
commit b8e62ab8dd
47 changed files with 2043 additions and 440 deletions

View File

@@ -17,7 +17,7 @@ from mealie.core.root_logger import get_logger
from mealie.db.models._model_base import SqlAlchemyBase
from mealie.schema._mealie import MealieModel
from mealie.schema.response.pagination import OrderByNullPosition, OrderDirection, PaginationBase, PaginationQuery
from mealie.schema.response.query_filter import QueryFilter
from mealie.schema.response.query_filter import QueryFilterBuilder
from mealie.schema.response.query_search import SearchFilter
from ._utils import NOT_SET, NotSet
@@ -349,8 +349,8 @@ class RepositoryGeneric(Generic[Schema, Model]):
if pagination.query_filter:
try:
query_filter = QueryFilter(pagination.query_filter)
query = query_filter.filter_query(query, model=self.model)
query_filter_builder = QueryFilterBuilder(pagination.query_filter)
query = query_filter_builder.filter_query(query, model=self.model)
except ValueError as e:
self.logger.error(e)
@@ -434,7 +434,7 @@ class RepositoryGeneric(Generic[Schema, Model]):
order_by = order_by_val
order_dir = pagination.order_direction
_, order_attr, query = QueryFilter.get_model_and_model_attr_from_attr_string(
_, order_attr, query = QueryFilterBuilder.get_model_and_model_attr_from_attr_string(
order_by, self.model, query=query
)

View File

@@ -19,13 +19,7 @@ from mealie.db.models.recipe.tool import Tool
from mealie.db.models.users.user_to_recipe import UserToRecipe
from mealie.schema.cookbook.cookbook import ReadCookBook
from mealie.schema.recipe import Recipe
from mealie.schema.recipe.recipe import (
RecipeCategory,
RecipePagination,
RecipeSummary,
RecipeTool,
)
from mealie.schema.recipe.recipe_category import CategoryBase, TagBase
from mealie.schema.recipe.recipe import RecipeCategory, RecipePagination, RecipeSummary
from mealie.schema.response.pagination import (
OrderByNullPosition,
OrderDirection,
@@ -33,7 +27,6 @@ from mealie.schema.response.pagination import (
)
from ..db.models._model_base import SqlAlchemyBase
from ..schema._mealie.mealie_model import extract_uuids
from .repository_generic import HouseholdRepositoryGeneric
@@ -173,17 +166,12 @@ class RepositoryRecipes(HouseholdRepositoryGeneric[Recipe, RecipeModel]):
q = q.filter_by(**fltr)
if cookbook:
cb_filters = self._build_recipe_filter(
households=[cookbook.household_id],
categories=extract_uuids(cookbook.categories),
tags=extract_uuids(cookbook.tags),
tools=extract_uuids(cookbook.tools),
require_all_categories=cookbook.require_all_categories,
require_all_tags=cookbook.require_all_tags,
require_all_tools=cookbook.require_all_tools,
)
q = q.filter(*cb_filters)
if pagination_result.query_filter and cookbook.query_filter_string:
pagination_result.query_filter = (
f"({pagination_result.query_filter}) AND ({cookbook.query_filter_string})"
)
else:
pagination_result.query_filter = cookbook.query_filter_string
else:
category_ids = self._uuids_for_items(categories, Category)
tag_ids = self._uuids_for_items(tags, Tag)
@@ -290,26 +278,6 @@ class RepositoryRecipes(HouseholdRepositoryGeneric[Recipe, RecipeModel]):
fltr.append(RecipeModel.household_id.in_(households))
return fltr
def by_category_and_tags(
self,
categories: list[CategoryBase] | None = None,
tags: list[TagBase] | None = None,
tools: list[RecipeTool] | None = None,
require_all_categories: bool = True,
require_all_tags: bool = True,
require_all_tools: bool = True,
) -> list[Recipe]:
fltr = self._build_recipe_filter(
categories=extract_uuids(categories) if categories else None,
tags=extract_uuids(tags) if tags else None,
tools=extract_uuids(tools) if tools else None,
require_all_categories=require_all_categories,
require_all_tags=require_all_tags,
require_all_tools=require_all_tools,
)
stmt = sa.select(RecipeModel).filter(*fltr)
return [self.schema.model_validate(x) for x in self.session.execute(stmt).scalars().all()]
def get_random(self, limit=1) -> list[Recipe]:
stmt = sa.select(RecipeModel).order_by(sa.func.random()).limit(limit) # Postgres and SQLite specific
if self.group_id: