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