mirror of
https://github.com/mealie-recipes/mealie.git
synced 2026-02-07 16:33:10 -05:00
feat: added "cookbook" filter to recipe pagination to serve frontend (#1609)
* added cookbook filter to recipe pagination * fixed wrong filter var * restored cookbook sorting * reverted unnecessary var change
This commit is contained in:
@@ -14,6 +14,7 @@ from mealie.db.models.recipe.recipe import RecipeModel
|
||||
from mealie.db.models.recipe.settings import RecipeSettings
|
||||
from mealie.db.models.recipe.tag import Tag
|
||||
from mealie.db.models.recipe.tool import Tool
|
||||
from mealie.schema.cookbook.cookbook import ReadCookBook
|
||||
from mealie.schema.recipe import Recipe
|
||||
from mealie.schema.recipe.recipe import RecipeCategory, RecipePagination, RecipeSummary, RecipeTag, RecipeTool
|
||||
from mealie.schema.recipe.recipe_category import CategoryBase, TagBase
|
||||
@@ -134,6 +135,7 @@ class RepositoryRecipes(RepositoryGeneric[Recipe, RecipeModel]):
|
||||
pagination: PaginationQuery,
|
||||
override=None,
|
||||
load_food=False,
|
||||
cookbook: Optional[ReadCookBook] = None,
|
||||
categories: Optional[list[UUID4 | str]] = None,
|
||||
tags: Optional[list[UUID4 | str]] = None,
|
||||
tools: Optional[list[UUID4 | str]] = None,
|
||||
@@ -154,6 +156,18 @@ class RepositoryRecipes(RepositoryGeneric[Recipe, RecipeModel]):
|
||||
fltr = self._filter_builder()
|
||||
q = q.filter_by(**fltr)
|
||||
|
||||
if cookbook:
|
||||
cb_filters = self._category_tag_filters(
|
||||
cookbook.categories,
|
||||
cookbook.tags,
|
||||
cookbook.tools,
|
||||
cookbook.require_all_categories,
|
||||
cookbook.require_all_tags,
|
||||
cookbook.require_all_tools,
|
||||
)
|
||||
|
||||
q = q.filter(*cb_filters)
|
||||
|
||||
if categories:
|
||||
for category in categories:
|
||||
if isinstance(category, UUID):
|
||||
@@ -241,7 +255,7 @@ class RepositoryRecipes(RepositoryGeneric[Recipe, RecipeModel]):
|
||||
tool_ids = [x.id for x in tools]
|
||||
|
||||
if require_all_tools:
|
||||
fltr.extend(RecipeModel.tags.any(Tag.id == tag_id) for tag_id in tag_ids)
|
||||
fltr.extend(RecipeModel.tools.any(Tool.id == tool_id) for tool_id in tool_ids)
|
||||
else:
|
||||
fltr.append(RecipeModel.tools.any(Tool.id.in_(tool_ids)))
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ from typing import Optional
|
||||
from zipfile import ZipFile
|
||||
|
||||
import sqlalchemy
|
||||
from fastapi import BackgroundTasks, Depends, File, Form, HTTPException, Query, status
|
||||
from fastapi import BackgroundTasks, Depends, File, Form, HTTPException, Query, Request, status
|
||||
from fastapi.datastructures import UploadFile
|
||||
from fastapi.encoders import jsonable_encoder
|
||||
from fastapi.responses import JSONResponse
|
||||
@@ -16,11 +16,14 @@ from mealie.core import exceptions
|
||||
from mealie.core.dependencies import temporary_zip_path
|
||||
from mealie.core.dependencies.dependencies import temporary_dir, validate_recipe_token
|
||||
from mealie.core.security import create_recipe_slug_token
|
||||
from mealie.db.models.group.cookbook import CookBook
|
||||
from mealie.pkgs import cache
|
||||
from mealie.repos.repository_generic import RepositoryGeneric
|
||||
from mealie.repos.repository_recipes import RepositoryRecipes
|
||||
from mealie.routes._base import BaseCrudController, controller
|
||||
from mealie.routes._base.mixins import HttpRepo
|
||||
from mealie.routes._base.routers import MealieCrudRoute, UserAPIRouter
|
||||
from mealie.schema.cookbook.cookbook import ReadCookBook
|
||||
from mealie.schema.recipe import Recipe, RecipeImageTypes, ScrapeRecipe
|
||||
from mealie.schema.recipe.recipe import (
|
||||
CreateRecipe,
|
||||
@@ -54,6 +57,10 @@ class BaseRecipeController(BaseCrudController):
|
||||
def repo(self) -> RepositoryRecipes:
|
||||
return self.repos.recipes.by_group(self.group_id)
|
||||
|
||||
@cached_property
|
||||
def cookbooks_repo(self) -> RepositoryGeneric[ReadCookBook, CookBook]:
|
||||
return self.repos.cookbooks.by_group(self.group_id)
|
||||
|
||||
@cached_property
|
||||
def service(self) -> RecipeService:
|
||||
return RecipeService(self.repos, self.user, self.group)
|
||||
@@ -219,24 +226,40 @@ class RecipeController(BaseRecipeController):
|
||||
@router.get("", response_model=RecipePagination)
|
||||
def get_all(
|
||||
self,
|
||||
q: RecipePaginationQuery = Depends(RecipePaginationQuery),
|
||||
request: Request,
|
||||
q: RecipePaginationQuery = Depends(),
|
||||
cookbook: Optional[UUID4 | str] = Query(None),
|
||||
categories: Optional[list[UUID4 | str]] = Query(None),
|
||||
tags: Optional[list[UUID4 | str]] = Query(None),
|
||||
tools: Optional[list[UUID4 | str]] = Query(None),
|
||||
):
|
||||
cookbook_data: Optional[ReadCookBook] = None
|
||||
if cookbook:
|
||||
cb_match_attr = "slug" if isinstance(cookbook, str) else "id"
|
||||
cookbook_data = self.cookbooks_repo.get_one(cookbook, cb_match_attr)
|
||||
|
||||
if cookbook is None:
|
||||
raise HTTPException(status_code=404, detail="cookbook not found")
|
||||
|
||||
pagination_response = self.repo.page_all(
|
||||
pagination=q,
|
||||
load_food=q.load_food,
|
||||
cookbook=cookbook_data,
|
||||
categories=categories,
|
||||
tags=tags,
|
||||
tools=tools,
|
||||
)
|
||||
|
||||
pagination_response.set_pagination_guides(router.url_path_for("get_all"), q.dict())
|
||||
# merge default pagination with the request's query params
|
||||
query_params = q.dict() | {**request.query_params}
|
||||
pagination_response.set_pagination_guides(
|
||||
router.url_path_for("get_all"),
|
||||
{k: v for k, v in query_params.items() if v is not None},
|
||||
)
|
||||
|
||||
new_items = []
|
||||
for item in pagination_response.items:
|
||||
# Pydantic/FastAPI can't seem to serialize the ingredient field on thier own.
|
||||
# Pydantic/FastAPI can't seem to serialize the ingredient field on their own.
|
||||
new_item = item.__dict__
|
||||
|
||||
if q.load_food:
|
||||
|
||||
Reference in New Issue
Block a user