mirror of
https://github.com/mealie-recipes/mealie.git
synced 2026-02-26 09:43:19 -05:00
* Fix issue with parsing scraped nutrition * Attempt to clean nutrition info * Allow comma separator * Fix return type for clean_nutrition. Fail safe in case of unexpected type from scraper * Switch to using regex parsing * Formatting * Cleanup - empty strings no longer a concern
149 lines
5.7 KiB
Python
149 lines
5.7 KiB
Python
import datetime
|
|
from datetime import date
|
|
|
|
import sqlalchemy as sa
|
|
import sqlalchemy.orm as orm
|
|
from mealie.db.models.model_base import BaseMixins, SqlAlchemyBase
|
|
from mealie.db.models.recipe.api_extras import ApiExtras
|
|
from mealie.db.models.recipe.assets import RecipeAsset
|
|
from mealie.db.models.recipe.category import Category, recipes2categories
|
|
from mealie.db.models.recipe.ingredient import RecipeIngredient
|
|
from mealie.db.models.recipe.instruction import RecipeInstruction
|
|
from mealie.db.models.recipe.note import Note
|
|
from mealie.db.models.recipe.nutrition import Nutrition
|
|
from mealie.db.models.recipe.settings import RecipeSettings
|
|
from mealie.db.models.recipe.tag import Tag, recipes2tags
|
|
from mealie.db.models.recipe.tool import Tool
|
|
from sqlalchemy.ext.orderinglist import ordering_list
|
|
from sqlalchemy.orm import validates
|
|
|
|
|
|
class RecipeModel(SqlAlchemyBase, BaseMixins):
|
|
__tablename__ = "recipes"
|
|
# Database Specific
|
|
id = sa.Column(sa.Integer, primary_key=True)
|
|
|
|
# General Recipe Properties
|
|
name = sa.Column(sa.String, nullable=False)
|
|
description = sa.Column(sa.String)
|
|
image = sa.Column(sa.String)
|
|
|
|
# Time Related Properties
|
|
total_time = sa.Column(sa.String)
|
|
prep_time = sa.Column(sa.String)
|
|
perform_time = sa.Column(sa.String)
|
|
cook_time = 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")
|
|
recipe_category: list = orm.relationship("Category", secondary=recipes2categories, back_populates="recipes")
|
|
|
|
recipe_ingredient: list[RecipeIngredient] = orm.relationship(
|
|
"RecipeIngredient",
|
|
cascade="all, delete-orphan",
|
|
order_by="RecipeIngredient.position",
|
|
collection_class=ordering_list("position"),
|
|
)
|
|
recipe_instructions: list[RecipeInstruction] = orm.relationship(
|
|
"RecipeInstruction",
|
|
cascade="all, delete-orphan",
|
|
order_by="RecipeInstruction.position",
|
|
collection_class=ordering_list("position"),
|
|
)
|
|
|
|
comments: list = orm.relationship("RecipeComment", back_populates="recipe", cascade="all, delete, delete-orphan")
|
|
|
|
# Mealie Specific
|
|
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")
|
|
notes: list[Note] = orm.relationship("Note", cascade="all, delete-orphan")
|
|
rating = sa.Column(sa.Integer)
|
|
org_url = sa.Column(sa.String)
|
|
extras: list[ApiExtras] = orm.relationship("ApiExtras", cascade="all, delete-orphan")
|
|
|
|
# Time Stamp Properties
|
|
date_added = sa.Column(sa.Date, default=date.today)
|
|
date_updated = sa.Column(sa.DateTime)
|
|
|
|
# Favorited By
|
|
favorited_by_id = sa.Column(sa.Integer, sa.ForeignKey("users.id"))
|
|
favorited_by = orm.relationship("User", back_populates="favorite_recipes")
|
|
|
|
@validates("name")
|
|
def validate_name(self, key, name):
|
|
assert name != ""
|
|
return name
|
|
|
|
def __init__(
|
|
self,
|
|
session,
|
|
name: str = None,
|
|
description: str = None,
|
|
image: str = None,
|
|
recipe_yield: str = None,
|
|
recipe_ingredient: list[str] = None,
|
|
recipe_instructions: list[dict] = None,
|
|
recipeCuisine: str = None,
|
|
total_time: str = None,
|
|
prep_time: str = None,
|
|
cook_time: str = None,
|
|
nutrition: dict = None,
|
|
tools: list[str] = None,
|
|
perform_time: str = None,
|
|
slug: str = None,
|
|
recipe_category: list[str] = None,
|
|
tags: list[str] = None,
|
|
date_added: datetime.date = None,
|
|
notes: list[dict] = None,
|
|
rating: int = None,
|
|
org_url: str = None,
|
|
extras: dict = None,
|
|
assets: list = None,
|
|
settings: dict = None,
|
|
**_
|
|
) -> None:
|
|
self.name = name
|
|
self.description = description
|
|
self.image = image
|
|
self.recipeCuisine = recipeCuisine
|
|
|
|
self.nutrition = Nutrition(**nutrition) if nutrition else Nutrition()
|
|
|
|
self.tools = [Tool(tool=x) for x in tools] if tools else []
|
|
|
|
self.recipe_yield = recipe_yield
|
|
self.recipe_ingredient = [RecipeIngredient(**ingr, session=session) for ingr in recipe_ingredient]
|
|
self.assets = [RecipeAsset(**a) for a in assets]
|
|
self.recipe_instructions = [
|
|
RecipeInstruction(text=instruc.get("text"), title=instruc.get("title"), type=instruc.get("@type", None))
|
|
for instruc in recipe_instructions
|
|
]
|
|
self.total_time = total_time
|
|
self.prep_time = prep_time
|
|
self.perform_time = perform_time
|
|
self.cook_time = cook_time
|
|
|
|
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()
|
|
self.tags = [Tag.create_if_not_exist(session=session, name=tag) for tag in tags]
|
|
self.slug = slug
|
|
self.notes = [Note(**note) for note in notes]
|
|
self.rating = rating
|
|
self.org_url = org_url
|
|
self.extras = [ApiExtras(key=key, value=value) for key, value in extras.items()]
|
|
|
|
# Time Stampes
|
|
self.date_added = date_added
|
|
self.date_updated = datetime.datetime.now()
|
|
|
|
def update(self, **_):
|
|
"""Updated a database entry by removing nested rows and rebuilds the row through the __init__ functions"""
|
|
self.__init__(**_)
|