Load meal by ID
This commit is contained in:
parent
33169c69ef
commit
a137199400
4 changed files with 71 additions and 10 deletions
15
main.py
15
main.py
|
|
@ -117,8 +117,21 @@ async def get_meals(start: datetime.datetime, end: datetime.datetime, conn: sqli
|
|||
|
||||
return result
|
||||
|
||||
@app.get("/meals/{meal_id}")
|
||||
async def get_meal(meal_id: int, request: Request, conn: sqlite3.Connection = Depends(get_db)) -> meals.Meal:
|
||||
meal = await meals.find_meal_by_id(conn, meal_id)
|
||||
if not meal:
|
||||
return JSONResponse(status_code=404, content={'message': 'Meal not found'})
|
||||
|
||||
await meals.load_participants(conn, meal)
|
||||
await meals.load_recipes(conn, meal)
|
||||
await meals.load_extra_ingredients(conn, meal)
|
||||
|
||||
return meal
|
||||
|
||||
@app.post("/meals/")
|
||||
async def create_meal(meal: meals.Meal, conn: sqlite3.Connection = Depends(get_db)) -> meals.Meal:
|
||||
"""
|
||||
if not meal.chef:
|
||||
return JSONResponse(status_code=400, content={'message': 'Meal must have at least one chef'})
|
||||
|
||||
|
|
@ -127,6 +140,7 @@ async def create_meal(meal: meals.Meal, conn: sqlite3.Connection = Depends(get_d
|
|||
|
||||
if not meal.consumers:
|
||||
return JSONResponse(status_code=400, content={'message': 'Meal must have at least one consumer'})
|
||||
"""
|
||||
|
||||
if len(meal.recipes) == 0 and len(meal.extra_ingredients) == 0:
|
||||
return JSONResponse(status_code=400, content={'message': 'Meal must have at least one recipe or ingredient'})
|
||||
|
|
@ -135,6 +149,7 @@ async def create_meal(meal: meals.Meal, conn: sqlite3.Connection = Depends(get_d
|
|||
await conn.commit()
|
||||
return meal
|
||||
|
||||
|
||||
@app.get("/persons/")
|
||||
async def get_persons(conn: sqlite3.Connection = Depends(get_db)) -> List[meals.Person]:
|
||||
result = []
|
||||
|
|
|
|||
42
meals/db.py
42
meals/db.py
|
|
@ -1,7 +1,9 @@
|
|||
from typing import List, ClassVar
|
||||
from pydantic import BaseModel
|
||||
from persons import Person
|
||||
from ingredients import Ingredient
|
||||
from ingredients import Ingredient, insert_ingredient
|
||||
from products import Product
|
||||
from recipes import Recipe, row_to_recipe
|
||||
|
||||
import datetime
|
||||
|
||||
|
|
@ -45,6 +47,12 @@ async def insert_meal_participant(conn, meal_id: int, person_id: int, role: str)
|
|||
VALUES (?, ?, ?)
|
||||
''', (meal_id, person_id, role))
|
||||
|
||||
async def insert_meal_recipe(conn, meal_id: int, recipe_id: int):
|
||||
await conn.execute('''
|
||||
INSERT INTO MealRecipe (meal_id, recipe_id)
|
||||
VALUES (?, ?)
|
||||
''', (meal_id, recipe_id))
|
||||
|
||||
async def insert_meal(conn, meal: Meal):
|
||||
async with conn.execute('''
|
||||
INSERT INTO Meal (date)
|
||||
|
|
@ -61,6 +69,13 @@ async def insert_meal(conn, meal: Meal):
|
|||
for person in meal.consumers:
|
||||
await insert_meal_participant(conn, meal.id, person.id, 'consumer')
|
||||
|
||||
for recipe in meal.recipes:
|
||||
await insert_meal_recipe(conn, meal.id, recipe.id)
|
||||
|
||||
for ingredient in meal.extra_ingredients:
|
||||
ingredient.meal_id = meal.id
|
||||
await insert_ingredient(conn, ingredient)
|
||||
|
||||
async def find_meal_by_id(conn, meal_id: int) -> Meal:
|
||||
async with conn.execute(f'''
|
||||
SELECT {','.join(Meal.KEYS)} FROM Meal
|
||||
|
|
@ -103,4 +118,27 @@ async def load_participants(conn, meal: Meal) -> None:
|
|||
elif row[1] == 'consumer':
|
||||
meal.consumers.append(person)
|
||||
else:
|
||||
raise Exception(f'Unknown role: {row[1]}')
|
||||
raise Exception(f'Unknown role: {row[1]}')
|
||||
|
||||
async def load_recipes(conn, meal: Meal) -> None:
|
||||
async with conn.execute(f'''
|
||||
SELECT {','.join(Recipe.KEYS)} FROM Recipe
|
||||
JOIN MealRecipe ON MealRecipe.recipe_id = Recipe.id
|
||||
WHERE MealRecipe.meal_id = ?
|
||||
''', (meal.id,)) as cursor:
|
||||
async for row in cursor:
|
||||
meal.recipes.append(row_to_recipe(zip(Recipe.KEYS, row)))
|
||||
|
||||
async def load_extra_ingredients(conn, meal: Meal) -> None:
|
||||
ingredient_cols = [f'Ingredient.{k}' for k in Ingredient.KEYS]
|
||||
product_cols = [f'Product.{k}' for k in Product.KEYS]
|
||||
|
||||
async with conn.execute(f'''
|
||||
SELECT {','.join(ingredient_cols + product_cols)} FROM Ingredient
|
||||
JOIN Product ON Ingredient.product_id = Product.id
|
||||
WHERE meal_id = ?
|
||||
''', (meal.id,)) as cursor:
|
||||
async for row in cursor:
|
||||
ingredient = Ingredient(**{k:v for k,v in zip(Ingredient.KEYS, row[:len(Ingredient.KEYS)])})
|
||||
ingredient.product = Product(**{k:v for k,v in zip(Product.KEYS, row[len(Ingredient.KEYS):])})
|
||||
meal.extra_ingredients.append(ingredient)
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
from recipes.db import Recipe, insert_recipe, find_recipe_by_id, get_all, find_recipes_by_name
|
||||
from recipes.db import Recipe, insert_recipe, find_recipe_by_id, get_all, find_recipes_by_name, row_to_recipe
|
||||
from recipes.scraping import scrape_recipe_ldata as _scrape_recipe_ldata
|
||||
from ingredients import parse_ingredient_from_nlp as _parse_ingredient_from_nlp, match_existing_products as _match_existing_products
|
||||
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ import json
|
|||
|
||||
from ingredients import Ingredient
|
||||
|
||||
from pydantic import BaseModel
|
||||
from typing import List, ClassVar
|
||||
from pydantic import BaseModel, Field
|
||||
from typing import List, ClassVar, Tuple
|
||||
|
||||
class Recipe(BaseModel):
|
||||
KEYS: ClassVar[List[str]] = ['id', 'name', 'link', 'image_urls', 'raw_data']
|
||||
|
|
@ -31,8 +31,8 @@ async def insert_recipe(conn, recipe: Recipe):
|
|||
''', (recipe.name, recipe.link, recipe.raw_data, json.dumps(recipe.image_urls))) as cursor:
|
||||
recipe.id = cursor.lastrowid
|
||||
|
||||
def row_to_recipe(row) -> Recipe:
|
||||
d = {k:v for k,v in zip(Recipe.KEYS, row)}
|
||||
def row_to_recipe(col_tuples: List[Tuple[str, ...]]) -> Recipe:
|
||||
d = {k:v for k,v in col_tuples}
|
||||
d['image_urls'] = json.loads(d['image_urls'])
|
||||
return Recipe(**d)
|
||||
|
||||
|
|
@ -43,7 +43,7 @@ async def find_recipe_by_id(conn, recipe_id: int) -> Recipe:
|
|||
LIMIT 1
|
||||
''', (recipe_id,)) as cursor:
|
||||
async for row in cursor:
|
||||
return row_to_recipe(row)
|
||||
return row_to_recipe(zip(Recipe.KEYS, row))
|
||||
|
||||
async def find_recipes_by_name(conn, name: str) -> List[Recipe]:
|
||||
async with conn.execute(f'''
|
||||
|
|
@ -51,11 +51,19 @@ async def find_recipes_by_name(conn, name: str) -> List[Recipe]:
|
|||
WHERE name LIKE ?
|
||||
''', (f'%{name}%',)) as cursor:
|
||||
async for row in cursor:
|
||||
yield row_to_recipe(row)
|
||||
yield row_to_recipe(zip(Recipe.KEYS, row))
|
||||
|
||||
async def get_all(conn) -> List[Recipe]:
|
||||
async with conn.execute(f'''
|
||||
SELECT {','.join(Recipe.KEYS)} FROM Recipe
|
||||
''') as cursor:
|
||||
async for row in cursor:
|
||||
yield row_to_recipe(row)
|
||||
yield row_to_recipe(zip(Recipe.KEYS, row))
|
||||
|
||||
async def load_ingredients(conn, recipe: Recipe):
|
||||
async with conn.execute(f'''
|
||||
SELECT {','.join(Ingredient.KEYS)} FROM Ingredient
|
||||
WHERE recipe_id = ?
|
||||
''', (recipe.id,)) as cursor:
|
||||
async for row in cursor:
|
||||
recipe.ingredients.append(Ingredient(**{k:v for k,v in zip(Ingredient.KEYS, row)}))
|
||||
Loading…
Reference in a new issue