diff --git a/frontend/src/components/Recipe/RecipeViewer/index.vue b/frontend/src/components/Recipe/RecipeViewer/index.vue index da878c8d..dd1daf91 100644 --- a/frontend/src/components/Recipe/RecipeViewer/index.vue +++ b/frontend/src/components/Recipe/RecipeViewer/index.vue @@ -33,8 +33,7 @@
- + {{ $t("recipe.categories") }} diff --git a/mealie/app.py b/mealie/app.py index 13d325ce..75b2bb7a 100644 --- a/mealie/app.py +++ b/mealie/app.py @@ -2,13 +2,14 @@ import uvicorn from fastapi import FastAPI from mealie.core import root_logger - -# import utils.startup as startup from mealie.core.config import APP_VERSION, settings -from mealie.routes import backup_routes, debug_routes, migration_routes, theme_routes, utility_routes +from mealie.routes import (backup_routes, debug_routes, migration_routes, + theme_routes, utility_routes) from mealie.routes.groups import groups from mealie.routes.mealplans import mealplans -from mealie.routes.recipe import all_recipe_routes, category_routes, recipe_assets, recipe_crud_routes, tag_routes +from mealie.routes.recipe import (all_recipe_routes, category_routes, + recipe_assets, recipe_crud_routes, + tag_routes) from mealie.routes.site_settings import all_settings from mealie.routes.users import users @@ -51,11 +52,11 @@ def api_routers(): api_routers() -start_scheduler() @app.on_event("startup") def system_startup(): + start_scheduler() logger.info("-----SYSTEM STARTUP----- \n") logger.info("------APP SETTINGS------") logger.info(settings.json(indent=4, exclude={"SECRET", "DEFAULT_PASSWORD", "SFTP_PASSWORD", "SFTP_USERNAME"})) diff --git a/mealie/db/models/mealplan.py b/mealie/db/models/mealplan.py index 84e70d9c..8ee0cacf 100644 --- a/mealie/db/models/mealplan.py +++ b/mealie/db/models/mealplan.py @@ -9,7 +9,7 @@ from mealie.db.models.model_base import BaseMixins, SqlAlchemyBase class Meal(SqlAlchemyBase): __tablename__ = "meal" id = sa.Column(sa.Integer, primary_key=True) - parent_id = sa.Column(sa.String, sa.ForeignKey("mealplan.uid")) + parent_id = sa.Column(sa.Integer, sa.ForeignKey("mealplan.uid")) slug = sa.Column(sa.String) name = sa.Column(sa.String) date = sa.Column(sa.Date) diff --git a/mealie/db/models/recipe/api_extras.py b/mealie/db/models/recipe/api_extras.py index 222bb6c2..c4172cb4 100644 --- a/mealie/db/models/recipe/api_extras.py +++ b/mealie/db/models/recipe/api_extras.py @@ -5,7 +5,7 @@ from mealie.db.models.model_base import SqlAlchemyBase class ApiExtras(SqlAlchemyBase): __tablename__ = "api_extras" id = sa.Column(sa.Integer, primary_key=True) - parent_id = sa.Column(sa.String, sa.ForeignKey("recipes.id")) + parent_id = sa.Column(sa.Integer, sa.ForeignKey("recipes.id")) key_name = sa.Column(sa.String, unique=True) value = sa.Column(sa.String) diff --git a/mealie/db/models/recipe/assets.py b/mealie/db/models/recipe/assets.py index 2dba9735..7fb1dab0 100644 --- a/mealie/db/models/recipe/assets.py +++ b/mealie/db/models/recipe/assets.py @@ -5,7 +5,7 @@ from mealie.db.models.model_base import SqlAlchemyBase class RecipeAsset(SqlAlchemyBase): __tablename__ = "recipe_assets" id = sa.Column(sa.Integer, primary_key=True) - parent_id = sa.Column(sa.String, sa.ForeignKey("recipes.id")) + parent_id = sa.Column(sa.Integer, sa.ForeignKey("recipes.id")) name = sa.Column(sa.String) icon = sa.Column(sa.String) file_name = sa.Column(sa.String) diff --git a/mealie/db/models/recipe/category.py b/mealie/db/models/recipe/category.py index ffaa4863..bacb50fc 100644 --- a/mealie/db/models/recipe/category.py +++ b/mealie/db/models/recipe/category.py @@ -41,7 +41,7 @@ class Category(SqlAlchemyBase): id = sa.Column(sa.Integer, primary_key=True) name = sa.Column(sa.String, index=True, nullable=False) slug = sa.Column(sa.String, index=True, unique=True, nullable=False) - recipes = orm.relationship("RecipeModel", secondary=recipes2categories, back_populates="recipeCategory") + recipes = orm.relationship("RecipeModel", secondary=recipes2categories, back_populates="recipe_category") @validates("name") def validate_name(self, key, name): diff --git a/mealie/db/models/recipe/ingredient.py b/mealie/db/models/recipe/ingredient.py index 75c20d2d..b00f4c60 100644 --- a/mealie/db/models/recipe/ingredient.py +++ b/mealie/db/models/recipe/ingredient.py @@ -6,7 +6,7 @@ class RecipeIngredient(SqlAlchemyBase): __tablename__ = "recipes_ingredients" id = sa.Column(sa.Integer, primary_key=True) position = sa.Column(sa.Integer) - parent_id = sa.Column(sa.String, sa.ForeignKey("recipes.id")) + parent_id = sa.Column(sa.Integer, sa.ForeignKey("recipes.id")) ingredient = sa.Column(sa.String) def update(self, ingredient): diff --git a/mealie/db/models/recipe/instruction.py b/mealie/db/models/recipe/instruction.py index 5aa136ea..080ebcbd 100644 --- a/mealie/db/models/recipe/instruction.py +++ b/mealie/db/models/recipe/instruction.py @@ -5,7 +5,7 @@ from mealie.db.models.model_base import SqlAlchemyBase class RecipeInstruction(SqlAlchemyBase): __tablename__ = "recipe_instructions" id = sa.Column(sa.Integer, primary_key=True) - parent_id = sa.Column(sa.String, sa.ForeignKey("recipes.id")) + parent_id = sa.Column(sa.Integer, sa.ForeignKey("recipes.id")) position = sa.Column(sa.Integer) type = sa.Column(sa.String, default="") text = sa.Column(sa.String) diff --git a/mealie/db/models/recipe/note.py b/mealie/db/models/recipe/note.py index 8d37db58..28ee4630 100644 --- a/mealie/db/models/recipe/note.py +++ b/mealie/db/models/recipe/note.py @@ -5,7 +5,7 @@ from mealie.db.models.model_base import SqlAlchemyBase class Note(SqlAlchemyBase): __tablename__ = "notes" id = sa.Column(sa.Integer, primary_key=True) - parent_id = sa.Column(sa.String, sa.ForeignKey("recipes.id")) + parent_id = sa.Column(sa.Integer, sa.ForeignKey("recipes.id")) title = sa.Column(sa.String) text = sa.Column(sa.String) diff --git a/mealie/db/models/recipe/nutrition.py b/mealie/db/models/recipe/nutrition.py index 38f18108..5856e3de 100644 --- a/mealie/db/models/recipe/nutrition.py +++ b/mealie/db/models/recipe/nutrition.py @@ -5,29 +5,29 @@ from mealie.db.models.model_base import SqlAlchemyBase class Nutrition(SqlAlchemyBase): __tablename__ = "recipe_nutrition" id = sa.Column(sa.Integer, primary_key=True) - parent_id = sa.Column(sa.String, sa.ForeignKey("recipes.id")) + parent_id = sa.Column(sa.Integer, sa.ForeignKey("recipes.id")) calories = sa.Column(sa.String) - fatContent = sa.Column(sa.String) - fiberContent = sa.Column(sa.String) - proteinContent = sa.Column(sa.String) - carbohydrateContent = sa.Column(sa.String) - sodiumContent = sa.Column(sa.String) - sugarContent = sa.Column(sa.String) + fat_content = sa.Column(sa.String) + fiber_content = sa.Column(sa.String) + protein_content = sa.Column(sa.String) + carbohydrate_content = sa.Column(sa.String) + sodium_content = sa.Column(sa.String) + sugar_content = sa.Column(sa.String) def __init__( self, calories=None, - fatContent=None, - fiberContent=None, - proteinContent=None, - sodiumContent=None, - sugarContent=None, - carbohydrateContent=None, + fat_content=None, + fiber_content=None, + protein_content=None, + sodium_content=None, + sugar_content=None, + carbohydrate_content=None, ) -> None: self.calories = calories - self.fatContent = fatContent - self.fiberContent = fiberContent - self.proteinContent = proteinContent - self.sodiumContent = sodiumContent - self.sugarContent = sugarContent - self.carbohydrateContent = carbohydrateContent + self.fat_content = fat_content + self.fiber_content = fiber_content + self.protein_content = protein_content + self.sodium_content = sodium_content + self.sugar_content = sugar_content + self.carbohydrate_content = carbohydrate_content diff --git a/mealie/db/models/recipe/recipe.py b/mealie/db/models/recipe/recipe.py index 7c02abf0..b9ffbedf 100644 --- a/mealie/db/models/recipe/recipe.py +++ b/mealie/db/models/recipe/recipe.py @@ -27,24 +27,24 @@ class RecipeModel(SqlAlchemyBase, BaseMixins): name = sa.Column(sa.String, nullable=False) description = sa.Column(sa.String) image = sa.Column(sa.String) - totalTime = sa.Column(sa.String) - prepTime = sa.Column(sa.String) - performTime = sa.Column(sa.String) + total_time = sa.Column(sa.String) + prep_time = sa.Column(sa.String) + perform_time = sa.Column(sa.String) cookTime = sa.Column(sa.String) - recipeYield = sa.Column(sa.String) + recipe_yield = sa.Column(sa.String) recipeCuisine = sa.Column(sa.String) tools: list[Tool] = orm.relationship("Tool", cascade="all, delete-orphan") assets: list[RecipeAsset] = orm.relationship("RecipeAsset", cascade="all, delete-orphan") nutrition: Nutrition = orm.relationship("Nutrition", uselist=False, cascade="all, delete-orphan") - recipeCategory: list = orm.relationship("Category", secondary=recipes2categories, back_populates="recipes") + recipe_category: list = orm.relationship("Category", secondary=recipes2categories, back_populates="recipes") - recipeIngredient: list[RecipeIngredient] = orm.relationship( + recipe_ingredient: list[RecipeIngredient] = orm.relationship( "RecipeIngredient", cascade="all, delete-orphan", order_by="RecipeIngredient.position", collection_class=ordering_list("position"), ) - recipeInstructions: list[RecipeInstruction] = orm.relationship( + recipe_instructions: list[RecipeInstruction] = orm.relationship( "RecipeInstruction", cascade="all, delete-orphan", order_by="RecipeInstruction.position", @@ -55,10 +55,10 @@ class RecipeModel(SqlAlchemyBase, BaseMixins): slug = sa.Column(sa.String, index=True, unique=True) settings = orm.relationship("RecipeSettings", uselist=False, cascade="all, delete-orphan") tags: list[Tag] = orm.relationship("Tag", secondary=recipes2tags, back_populates="recipes") - dateAdded = sa.Column(sa.Date, default=date.today) + date_added = sa.Column(sa.Date, default=date.today) notes: list[Note] = orm.relationship("Note", cascade="all, delete-orphan") rating = sa.Column(sa.Integer) - orgURL = sa.Column(sa.String) + org_url = sa.Column(sa.String) extras: list[ApiExtras] = orm.relationship("ApiExtras", cascade="all, delete-orphan") @validates("name") @@ -72,22 +72,22 @@ class RecipeModel(SqlAlchemyBase, BaseMixins): name: str = None, description: str = None, image: str = None, - recipeYield: str = None, - recipeIngredient: list[str] = None, - recipeInstructions: list[dict] = None, + recipe_yield: str = None, + recipe_ingredient: list[str] = None, + recipe_instructions: list[dict] = None, recipeCuisine: str = None, - totalTime: str = None, - prepTime: str = None, + total_time: str = None, + prep_time: str = None, nutrition: dict = None, tools: list[str] = None, - performTime: str = None, + perform_time: str = None, slug: str = None, - recipeCategory: list[str] = None, + recipe_category: list[str] = None, tags: list[str] = None, - dateAdded: datetime.date = None, + date_added: datetime.date = None, notes: list[dict] = None, rating: int = None, - orgURL: str = None, + org_url: str = None, extras: dict = None, assets: list = None, settings: dict = None, @@ -103,28 +103,28 @@ class RecipeModel(SqlAlchemyBase, BaseMixins): self.tools = [Tool(tool=x) for x in tools] if tools else [] - self.recipeYield = recipeYield - self.recipeIngredient = [RecipeIngredient(ingredient=ingr) for ingr in recipeIngredient] + self.recipe_yield = recipe_yield + self.recipe_ingredient = [RecipeIngredient(ingredient=ingr) for ingr in recipe_ingredient] self.assets = [RecipeAsset(**a) for a in assets] - self.recipeInstructions = [ + self.recipe_instructions = [ RecipeInstruction(text=instruc.get("text"), title=instruc.get("title"), type=instruc.get("@type", None)) - for instruc in recipeInstructions + for instruc in recipe_instructions ] - self.totalTime = totalTime - self.prepTime = prepTime - self.performTime = performTime + self.total_time = total_time + self.prep_time = prep_time + self.perform_time = perform_time - self.recipeCategory = [Category.create_if_not_exist(session=session, name=cat) for cat in recipeCategory] + self.recipe_category = [Category.create_if_not_exist(session=session, name=cat) for cat in recipe_category] # Mealie Specific self.settings = RecipeSettings(**settings) if settings else RecipeSettings() print(self.settings) self.tags = [Tag.create_if_not_exist(session=session, name=tag) for tag in tags] self.slug = slug - self.dateAdded = dateAdded + self.date_added = date_added self.notes = [Note(**note) for note in notes] self.rating = rating - self.orgURL = orgURL + self.org_url = org_url self.extras = [ApiExtras(key=key, value=value) for key, value in extras.items()] def update(self, *args, **kwargs): diff --git a/mealie/db/models/recipe/tool.py b/mealie/db/models/recipe/tool.py index 6b65c9e5..2406864f 100644 --- a/mealie/db/models/recipe/tool.py +++ b/mealie/db/models/recipe/tool.py @@ -5,7 +5,7 @@ from mealie.db.models.model_base import SqlAlchemyBase class Tool(SqlAlchemyBase): __tablename__ = "tools" id = sa.Column(sa.Integer, primary_key=True) - parent_id = sa.Column(sa.String, sa.ForeignKey("recipes.id")) + parent_id = sa.Column(sa.Integer, sa.ForeignKey("recipes.id")) tool = sa.Column(sa.String) def __init__(self, tool) -> None: diff --git a/mealie/routes/mealplans/helpers.py b/mealie/routes/mealplans/helpers.py index 1e64cb50..15ce140b 100644 --- a/mealie/routes/mealplans/helpers.py +++ b/mealie/routes/mealplans/helpers.py @@ -21,4 +21,4 @@ def get_shopping_list( mealplan: MealPlanInDB slugs = [x.slug for x in mealplan.meals] recipes: list[Recipe] = [db.recipes.get(session, x) for x in slugs] - return [{"name": x.name, "recipeIngredient": x.recipeIngredient} for x in recipes if x] + return [{"name": x.name, "recipe_ingredient": x.recipe_ingredient} for x in recipes if x] diff --git a/mealie/routes/recipe/all_recipe_routes.py b/mealie/routes/recipe/all_recipe_routes.py index da07ed18..0a8556af 100644 --- a/mealie/routes/recipe/all_recipe_routes.py +++ b/mealie/routes/recipe/all_recipe_routes.py @@ -50,11 +50,11 @@ def get_all_recipes( - description - image - recipeYield - - totalTime - - prepTime - - performTime + - total_time + - prep_time + - perform_time - rating - - orgURL + - org_url **Note:** You may experience problems with with query parameters. As an alternative you may also use the post method and provide a body. @@ -78,11 +78,11 @@ def get_all_recipes_post(body: AllRecipeRequest, session: Session = Depends(gene - description - image - recipeYield - - totalTime - - prepTime - - performTime + - total_time + - prep_time + - perform_time - rating - - orgURL + - org_url Refer to the body example for data formats. diff --git a/mealie/schema/recipe.py b/mealie/schema/recipe.py index 0b707633..1ff2aabf 100644 --- a/mealie/schema/recipe.py +++ b/mealie/schema/recipe.py @@ -43,27 +43,27 @@ class RecipeAsset(CamelModel): orm_mode = True -class Nutrition(BaseModel): +class Nutrition(CamelModel): calories: Optional[str] - fatContent: Optional[str] - proteinContent: Optional[str] - carbohydrateContent: Optional[str] - fiberContent: Optional[str] - sodiumContent: Optional[str] - sugarContent: Optional[str] + fat_content: Optional[str] + protein_content: Optional[str] + carbohydrate_content: Optional[str] + fiber_content: Optional[str] + sodium_content: Optional[str] + sugar_content: Optional[str] class Config: orm_mode = True -class RecipeSummary(BaseModel): +class RecipeSummary(CamelModel): id: Optional[int] name: str slug: Optional[str] = "" image: Optional[Any] description: Optional[str] - recipeCategory: Optional[list[str]] = [] + recipe_category: Optional[list[str]] = [] tags: Optional[list[str]] = [] rating: Optional[int] @@ -74,28 +74,28 @@ class RecipeSummary(BaseModel): def getter_dict(_cls, name_orm: RecipeModel): return { **GetterDict(name_orm), - "recipeCategory": [x.name for x in name_orm.recipeCategory], + "recipe_category": [x.name for x in name_orm.recipe_category], "tags": [x.name for x in name_orm.tags], } class Recipe(RecipeSummary): - recipeYield: Optional[str] - recipeIngredient: Optional[list[str]] - recipeInstructions: Optional[list[RecipeStep]] + recipe_yield: Optional[str] + recipe_ingredient: Optional[list[str]] + recipe_instructions: Optional[list[RecipeStep]] nutrition: Optional[Nutrition] tools: Optional[list[str]] = [] - totalTime: Optional[str] = None - prepTime: Optional[str] = None - performTime: Optional[str] = None + total_time: Optional[str] = None + prep_time: Optional[str] = None + perform_time: Optional[str] = None # Mealie Specific settings: Optional[RecipeSettings] assets: Optional[list[RecipeAsset]] = [] - dateAdded: Optional[datetime.date] + date_added: Optional[datetime.date] notes: Optional[list[RecipeNote]] = [] - orgURL: Optional[str] + org_url: Optional[str] = Field(None, alias="orgURL") extras: Optional[dict] = {} class Config: @@ -105,8 +105,8 @@ class Recipe(RecipeSummary): def getter_dict(_cls, name_orm: RecipeModel): return { **GetterDict(name_orm), - "recipeIngredient": [x.ingredient for x in name_orm.recipeIngredient], - "recipeCategory": [x.name for x in name_orm.recipeCategory], + "recipe_ingredient": [x.ingredient for x in name_orm.recipe_ingredient], + "recipe_category": [x.name for x in name_orm.recipe_category], "tags": [x.name for x in name_orm.tags], "tools": [x.tool for x in name_orm.tools], "extras": {x.key_name: x.value for x in name_orm.extras}, @@ -117,22 +117,22 @@ class Recipe(RecipeSummary): "name": "Chicken and Rice With Leeks and Salsa Verde", "description": "This one-skillet dinner gets deep oniony flavor from lots of leeks cooked down to jammy tenderness.", "image": "chicken-and-rice-with-leeks-and-salsa-verde.jpg", - "recipeYield": "4 Servings", - "recipeIngredient": [ + "recipe_yield": "4 Servings", + "recipe_ingredient": [ "1 1/2 lb. skinless, boneless chicken thighs (4-8 depending on size)", "Kosher salt, freshly ground pepper", "3 Tbsp. unsalted butter, divided", ], - "recipeInstructions": [ + "recipe_instructions": [ { "text": "Season chicken with salt and pepper.", }, ], "slug": "chicken-and-rice-with-leeks-and-salsa-verde", "tags": ["favorite", "yummy!"], - "recipeCategory": ["Dinner", "Pasta"], + "recipe_category": ["Dinner", "Pasta"], "notes": [{"title": "Watch Out!", "text": "Prep the day before!"}], - "orgURL": "https://www.bonappetit.com/recipe/chicken-and-rice-with-leeks-and-salsa-verde", + "org_url": "https://www.bonappetit.com/recipe/chicken-and-rice-with-leeks-and-salsa-verde", "rating": 3, "extras": {"message": "Don't forget to defrost the chicken!"}, } diff --git a/mealie/services/backups/imports.py b/mealie/services/backups/imports.py index 2b8bf33e..3d35a843 100644 --- a/mealie/services/backups/imports.py +++ b/mealie/services/backups/imports.py @@ -83,7 +83,7 @@ class ImportDatabase: del recipe_dict["categories"] try: del recipe_dict["_id"] - del recipe_dict["dateAdded"] + del recipe_dict["date_added"] except: pass # Migration from list to Object Type Data diff --git a/mealie/services/migrations/_migration_base.py b/mealie/services/migrations/_migration_base.py index ea5d4f7a..15434d5b 100644 --- a/mealie/services/migrations/_migration_base.py +++ b/mealie/services/migrations/_migration_base.py @@ -144,7 +144,7 @@ class MigrationBase(BaseModel): """Calls the rewrite_alias function and the Cleaner.clean function on a dictionary and returns the result unpacked into a Recipe object""" recipe_dict = self.rewrite_alias(recipe_dict) - recipe_dict = Cleaner.clean(recipe_dict, url=recipe_dict.get("orgURL", None)) + recipe_dict = Cleaner.clean(recipe_dict, url=recipe_dict.get("org_url", None)) return Recipe(**recipe_dict) diff --git a/mealie/services/migrations/nextcloud.py b/mealie/services/migrations/nextcloud.py index 48461e61..c8b589c9 100644 --- a/mealie/services/migrations/nextcloud.py +++ b/mealie/services/migrations/nextcloud.py @@ -37,7 +37,7 @@ class NextcloudDir: class NextcloudMigration(MigrationBase): key_aliases: Optional[list[MigrationAlias]] = [ MigrationAlias(key="tags", alias="keywords", func=helpers.split_by_comma), - MigrationAlias(key="orgURL", alias="url", func=None), + MigrationAlias(key="org_url", alias="url", func=None), ] diff --git a/tests/conftest.py b/tests/conftest.py index 36107adc..74b34c49 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,9 +1,16 @@ +from mealie.core.config import app_dirs, settings + +#! I don't like it either! +SQLITE_FILE = app_dirs.SQLITE_DIR.joinpath("test.db") +SQLITE_FILE.unlink(missing_ok=True) + +settings.SQLITE_FILE = SQLITE_FILE + import json import requests from fastapi.testclient import TestClient from mealie.app import app -from mealie.core.config import app_dirs, settings from mealie.db.db_setup import generate_session, sql_global_init from mealie.db.init_db import init_db from pytest import fixture @@ -12,10 +19,6 @@ from tests.app_routes import AppRoutes from tests.test_config import TEST_DATA from tests.utils.recipe_data import build_recipe_store, get_raw_no_image, get_raw_recipe -SQLITE_FILE = app_dirs.SQLITE_DIR.joinpath("test.db") -SQLITE_FILE.unlink(missing_ok=True) - - TestSessionLocal = sql_global_init(SQLITE_FILE, check_thread=False) init_db(TestSessionLocal())