feat: category and tag filters to recipe pagination route (#1508)

* fixed incorrect response model

* added category and tag filters

* moved categories and tags params to route and
changed to query array param

* type fixes

* added category and tag tests
This commit is contained in:
Michael Genson
2022-08-09 17:01:59 -05:00
committed by GitHub
parent e82e7d0fb3
commit f45e2587a0
3 changed files with 219 additions and 19 deletions

View File

@@ -129,7 +129,14 @@ class RepositoryRecipes(RepositoryGeneric[Recipe, RecipeModel]):
.all()
)
def page_all(self, pagination: PaginationQuery, override=None, load_food=False) -> RecipePagination:
def page_all(
self,
pagination: PaginationQuery,
override=None,
load_food=False,
categories: Optional[list[UUID4 | str]] = None,
tags: Optional[list[UUID4 | str]] = None,
) -> RecipePagination:
q = self.session.query(self.model)
args = [
@@ -145,6 +152,23 @@ class RepositoryRecipes(RepositoryGeneric[Recipe, RecipeModel]):
fltr = self._filter_builder()
q = q.filter_by(**fltr)
if categories:
for category in categories:
if isinstance(category, UUID):
q = q.filter(RecipeModel.recipe_category.any(Category.id == category))
else:
q = q.filter(RecipeModel.recipe_category.any(Category.slug == category))
if tags:
for tag in tags:
if isinstance(tag, UUID):
q = q.filter(RecipeModel.tags.any(Tag.id == tag))
else:
q = q.filter(RecipeModel.tags.any(Tag.slug == tag))
q, count, total_pages = self.add_pagination_to_query(q, pagination)
try:

View File

@@ -1,13 +1,14 @@
from functools import cached_property
from shutil import copyfileobj
from typing import Optional
from zipfile import ZipFile
import sqlalchemy
from fastapi import BackgroundTasks, Depends, File, Form, HTTPException, status
from fastapi import BackgroundTasks, Depends, File, Form, HTTPException, Query, status
from fastapi.datastructures import UploadFile
from fastapi.encoders import jsonable_encoder
from fastapi.responses import JSONResponse
from pydantic import BaseModel, Field
from pydantic import UUID4, BaseModel, Field
from slugify import slugify
from starlette.responses import FileResponse
@@ -21,7 +22,13 @@ from mealie.routes._base import BaseUserController, controller
from mealie.routes._base.mixins import HttpRepo
from mealie.routes._base.routers import MealieCrudRoute, UserAPIRouter
from mealie.schema.recipe import Recipe, RecipeImageTypes, ScrapeRecipe
from mealie.schema.recipe.recipe import CreateRecipe, CreateRecipeByUrlBulk, RecipePaginationQuery, RecipeSummary
from mealie.schema.recipe.recipe import (
CreateRecipe,
CreateRecipeByUrlBulk,
RecipePagination,
RecipePaginationQuery,
RecipeSummary,
)
from mealie.schema.recipe.recipe_asset import RecipeAsset
from mealie.schema.recipe.recipe_scraper import ScrapeRecipeTest
from mealie.schema.recipe.request_helpers import RecipeZipTokenResponse, UpdateImageResponse
@@ -200,11 +207,18 @@ class RecipeController(BaseRecipeController):
# ==================================================================================================================
# CRUD Operations
@router.get("", response_model=list[RecipeSummary])
def get_all(self, q: RecipePaginationQuery = Depends(RecipePaginationQuery)):
@router.get("", response_model=RecipePagination)
def get_all(
self,
q: RecipePaginationQuery = Depends(RecipePaginationQuery),
categories: Optional[list[UUID4 | str]] = Query(None),
tags: Optional[list[UUID4 | str]] = Query(None),
):
response = self.repo.page_all(
pagination=q,
load_food=q.load_food,
categories=categories,
tags=tags,
)
response.set_pagination_guides(router.url_path_for("get_all"), q.dict())