mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-07-09 03:04:54 -04:00
fix auto initialize models
This commit is contained in:
parent
24a4b5b810
commit
abb0b84e22
@ -5,6 +5,7 @@ from mealie.db.db_setup import SessionLocal
|
||||
from sqlalchemy import Column, DateTime, Integer
|
||||
from sqlalchemy.ext.declarative import as_declarative
|
||||
from sqlalchemy.orm import declarative_base
|
||||
from sqlalchemy.orm.session import Session
|
||||
|
||||
|
||||
def get_uuid_as_hex() -> str:
|
||||
@ -38,15 +39,15 @@ class BaseMixins:
|
||||
self.__init__(*args, **kwarg)
|
||||
|
||||
@classmethod
|
||||
def get_ref(cls, match_value: str, match_attr: str = None):
|
||||
def get_ref(cls, match_value: str, match_attr: str = None, session: Session = None):
|
||||
match_attr = match_attr = cls.Config.get_attr
|
||||
|
||||
if match_value is None:
|
||||
if match_value is None or session is None:
|
||||
return None
|
||||
|
||||
with SessionLocal() as session:
|
||||
eff_ref = getattr(cls, match_attr)
|
||||
return session.query(cls).filter(eff_ref == match_value).one_or_none()
|
||||
eff_ref = getattr(cls, match_attr)
|
||||
|
||||
return session.query(cls).filter(eff_ref == match_value).one_or_none()
|
||||
|
||||
|
||||
SqlAlchemyBase = declarative_base(cls=Base, constructor=None)
|
||||
|
@ -56,6 +56,8 @@ def auto_init(exclude: Union[set, list] = None): # sourcery no-metrics
|
||||
model_columns = self.__mapper__.columns
|
||||
relationships = self.__mapper__.relationships
|
||||
|
||||
session = kwargs.get("session", None)
|
||||
|
||||
for key, val in kwargs.items():
|
||||
if key in exclude:
|
||||
continue
|
||||
@ -86,24 +88,22 @@ def auto_init(exclude: Union[set, list] = None): # sourcery no-metrics
|
||||
val = val.get("id")
|
||||
|
||||
if val is None:
|
||||
raise ValueError(
|
||||
f"Expected 'id' to be provided for {key}"
|
||||
)
|
||||
raise ValueError(f"Expected 'id' to be provided for {key}")
|
||||
|
||||
if isinstance(val, (str, int)):
|
||||
instance = relation_cls.get_ref(match_value=val)
|
||||
instance = relation_cls.get_ref(match_value=val, session=session)
|
||||
setattr(self, key, instance)
|
||||
|
||||
elif relation_dir == MANYTOMANY.name:
|
||||
if not isinstance(val, list):
|
||||
raise ValueError(
|
||||
f"Expected many to many input to be of type list for {key}"
|
||||
)
|
||||
|
||||
if isinstance(val[0], dict):
|
||||
if not isinstance(val, list):
|
||||
raise ValueError(f"Expected many to many input to be of type list for {key}")
|
||||
|
||||
if len(val) > 0 and isinstance(val[0], dict):
|
||||
val = [elem.get("id") for elem in val]
|
||||
intstances = [relation_cls.get_ref(elem) for elem in val]
|
||||
setattr(self, key, intstances)
|
||||
|
||||
instances = [relation_cls.get_ref(elem, session=session) for elem in val]
|
||||
setattr(self, key, instances)
|
||||
|
||||
return init(self, *args, **kwargs)
|
||||
|
||||
|
@ -1,9 +1,12 @@
|
||||
from functools import lru_cache
|
||||
|
||||
import sqlalchemy as sa
|
||||
import sqlalchemy.orm as orm
|
||||
from mealie.core import root_logger
|
||||
from mealie.db.db_setup import SessionLocal
|
||||
from mealie.db.models._model_base import BaseMixins, SqlAlchemyBase
|
||||
from slugify import slugify
|
||||
from sqlalchemy import inspect
|
||||
from sqlalchemy.orm import validates
|
||||
|
||||
logger = root_logger.get_logger()
|
||||
@ -56,14 +59,15 @@ class Category(SqlAlchemyBase, BaseMixins):
|
||||
self.name = name.strip()
|
||||
self.slug = slugify(name)
|
||||
|
||||
@staticmethod
|
||||
def create_if_not_exist(name: str = None):
|
||||
test_slug = slugify(name)
|
||||
with SessionLocal() as session:
|
||||
result = session.query(Category).filter(Category.slug == test_slug).one_or_none()
|
||||
if result:
|
||||
logger.debug("Category exists, associating recipe")
|
||||
return result
|
||||
else:
|
||||
logger.debug("Category doesn't exists, creating tag")
|
||||
return Category(name=name)
|
||||
@classmethod
|
||||
def get_ref(cls, match_value: str, session=None):
|
||||
if not session or not match_value:
|
||||
return None
|
||||
|
||||
result = session.query(Category).filter(Category.name == match_value).one_or_none()
|
||||
if result:
|
||||
logger.debug("Category exists, associating recipe")
|
||||
return result
|
||||
else:
|
||||
logger.debug("Category doesn't exists, creating Category")
|
||||
return Category(name=match_value)
|
||||
|
@ -1,23 +1,8 @@
|
||||
from mealie.db.models._model_base import BaseMixins, SqlAlchemyBase
|
||||
from requests import Session
|
||||
from sqlalchemy import Column, ForeignKey, Integer, String, Table, orm
|
||||
from sqlalchemy import Column, ForeignKey, Integer, String, orm
|
||||
|
||||
from .._model_utils import auto_init
|
||||
|
||||
ingredients_to_units = Table(
|
||||
"ingredients_to_units",
|
||||
SqlAlchemyBase.metadata,
|
||||
Column("ingredient_units.id", Integer, ForeignKey("ingredient_units.id")),
|
||||
Column("recipes_ingredients_id", Integer, ForeignKey("recipes_ingredients.id")),
|
||||
)
|
||||
|
||||
ingredients_to_foods = Table(
|
||||
"ingredients_to_foods",
|
||||
SqlAlchemyBase.metadata,
|
||||
Column("ingredient_foods.id", Integer, ForeignKey("ingredient_foods.id")),
|
||||
Column("recipes_ingredients_id", Integer, ForeignKey("recipes_ingredients.id")),
|
||||
)
|
||||
|
||||
|
||||
class IngredientUnitModel(SqlAlchemyBase, BaseMixins):
|
||||
__tablename__ = "ingredient_units"
|
||||
@ -25,7 +10,7 @@ class IngredientUnitModel(SqlAlchemyBase, BaseMixins):
|
||||
name = Column(String)
|
||||
description = Column(String)
|
||||
abbreviation = Column(String)
|
||||
ingredients = orm.relationship("RecipeIngredient", secondary=ingredients_to_units, back_populates="unit")
|
||||
ingredients = orm.relationship("RecipeIngredient", back_populates="unit")
|
||||
|
||||
@auto_init()
|
||||
def __init__(self, **_) -> None:
|
||||
@ -37,7 +22,7 @@ class IngredientFoodModel(SqlAlchemyBase, BaseMixins):
|
||||
id = Column(Integer, primary_key=True)
|
||||
name = Column(String)
|
||||
description = Column(String)
|
||||
ingredients = orm.relationship("RecipeIngredient", secondary=ingredients_to_foods, back_populates="food")
|
||||
ingredients = orm.relationship("RecipeIngredient", back_populates="food")
|
||||
|
||||
@auto_init()
|
||||
def __init__(self, **_) -> None:
|
||||
@ -54,19 +39,15 @@ class RecipeIngredient(SqlAlchemyBase, BaseMixins):
|
||||
note = Column(String) # Force Show Text - Overrides Concat
|
||||
|
||||
# Scaling Items
|
||||
unit = orm.relationship(IngredientUnitModel, secondary=ingredients_to_units, uselist=False)
|
||||
food = orm.relationship(IngredientFoodModel, secondary=ingredients_to_foods, uselist=False)
|
||||
unit_id = Column(Integer, ForeignKey("ingredient_units.id"))
|
||||
unit = orm.relationship(IngredientUnitModel, uselist=False)
|
||||
|
||||
food_id = Column(Integer, ForeignKey("ingredient_foods.id"))
|
||||
food = orm.relationship(IngredientFoodModel, uselist=False)
|
||||
quantity = Column(Integer)
|
||||
|
||||
# Extras
|
||||
|
||||
def __init__(self, title: str, note: str, unit: dict, food: dict, quantity: int, session: Session, **_) -> None:
|
||||
self.title = title
|
||||
self.note = note
|
||||
self.quantity = quantity
|
||||
|
||||
if unit:
|
||||
self.unit = IngredientUnitModel.get_ref(unit.get("id"))
|
||||
|
||||
if food:
|
||||
self.food = IngredientFoodModel.get_ref(unit.get("id"))
|
||||
@auto_init()
|
||||
def __init__(self, **_) -> None:
|
||||
pass
|
||||
|
@ -7,6 +7,7 @@ from sqlalchemy.ext.orderinglist import ordering_list
|
||||
from sqlalchemy.orm import validates
|
||||
|
||||
from .._model_base import BaseMixins, SqlAlchemyBase
|
||||
from .._model_utils import auto_init
|
||||
from .api_extras import ApiExtras
|
||||
from .assets import RecipeAsset
|
||||
from .category import Category, recipes2categories
|
||||
@ -77,66 +78,44 @@ class RecipeModel(SqlAlchemyBase, BaseMixins):
|
||||
assert name != ""
|
||||
return name
|
||||
|
||||
@auto_init(
|
||||
{
|
||||
"assets",
|
||||
"extras",
|
||||
"notes",
|
||||
"nutrition",
|
||||
"recipe_ingredient",
|
||||
"recipe_instructions",
|
||||
"settings",
|
||||
"tools",
|
||||
}
|
||||
)
|
||||
def __init__(
|
||||
self,
|
||||
session,
|
||||
name: str = None,
|
||||
description: str = None,
|
||||
image: str = None,
|
||||
recipe_yield: str = None,
|
||||
assets: list = None,
|
||||
extras: dict = None,
|
||||
notes: list[dict] = None,
|
||||
nutrition: dict = 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,
|
||||
tools: list[str] = None,
|
||||
**_
|
||||
) -> None:
|
||||
self.name = name
|
||||
self.description = description
|
||||
self.image = image
|
||||
self.recipeCuisine = recipeCuisine
|
||||
|
||||
self.nutrition = Nutrition(**nutrition) if self.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 = [x for x in [Category.create_if_not_exist(cat) for cat in recipe_category] if x]
|
||||
|
||||
# Mealie Specific
|
||||
self.settings = RecipeSettings(**settings) if settings else RecipeSettings()
|
||||
self.tags = [Tag.create_if_not_exist(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()
|
||||
|
Loading…
x
Reference in New Issue
Block a user