mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-12-15 06:45:23 -05:00
feature/new-feature-cleanup (#389)
* add json editor to theme editor * add toolbars tools to recipe sections * fix recipe yield * add updated_date to recipe schema * update time cards * fix mobile buttons * fix asset URL * fix PG errors CRUD * remove -d from docker-pro * fix theme tests * remvoe old typing * abstract count function Co-authored-by: hay-kot <hay-kot@pm.me>
This commit is contained in:
@@ -37,24 +37,14 @@ class _Recipes(BaseDocument):
|
||||
return f"{slug}.{extension}"
|
||||
|
||||
def count_uncategorized(self, session: Session, count=True, override_schema=None) -> int:
|
||||
eff_schema = override_schema or self.schema
|
||||
if count:
|
||||
return session.query(self.sql_model).filter(RecipeModel.recipe_category == None).count() # noqa: 711
|
||||
else:
|
||||
return [
|
||||
eff_schema.from_orm(x)
|
||||
for x in session.query(self.sql_model).filter(RecipeModel.tags == None).all() # noqa: 711
|
||||
]
|
||||
return self._countr_attribute(
|
||||
session, attribute_name=RecipeModel.recipe_category, attr_match=None, count=True, override_schema=None
|
||||
)
|
||||
|
||||
def count_untagged(self, session: Session, count=True, override_schema=None) -> int:
|
||||
eff_schema = override_schema or self.schema
|
||||
if count:
|
||||
return session.query(self.sql_model).filter(RecipeModel.tags == None).count() # noqa: 711
|
||||
else:
|
||||
return [
|
||||
eff_schema.from_orm(x)
|
||||
for x in session.query(self.sql_model).filter(RecipeModel.tags == None).all() # noqa: 711
|
||||
]
|
||||
return self._countr_attribute(
|
||||
session, attribute_name=RecipeModel.tags, attr_match=None, count=True, override_schema=None
|
||||
)
|
||||
|
||||
|
||||
class _Categories(BaseDocument):
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from typing import List
|
||||
from typing import Union
|
||||
|
||||
from mealie.core.root_logger import get_logger
|
||||
from mealie.db.models.model_base import SqlAlchemyBase
|
||||
@@ -20,7 +20,7 @@ class BaseDocument:
|
||||
# TODO: Improve Get All Query Functionality
|
||||
def get_all(
|
||||
self, session: Session, limit: int = None, order_by: str = None, start=0, end=9999, override_schema=None
|
||||
) -> List[dict]:
|
||||
) -> list[dict]:
|
||||
eff_schema = override_schema or self.schema
|
||||
|
||||
if order_by:
|
||||
@@ -33,13 +33,13 @@ class BaseDocument:
|
||||
|
||||
return [eff_schema.from_orm(x) for x in session.query(self.sql_model).offset(start).limit(limit).all()]
|
||||
|
||||
def get_all_limit_columns(self, session: Session, fields: List[str], limit: int = None) -> List[SqlAlchemyBase]:
|
||||
def get_all_limit_columns(self, session: Session, fields: list[str], limit: int = None) -> list[SqlAlchemyBase]:
|
||||
"""Queries the database for the selected model. Restricts return responses to the
|
||||
keys specified under "fields"
|
||||
|
||||
Args: \n
|
||||
session (Session): Database Session Object
|
||||
fields (List[str]): List of column names to query
|
||||
fields (list[str]): list of column names to query
|
||||
limit (int): A limit of values to return
|
||||
|
||||
Returns:
|
||||
@@ -47,7 +47,7 @@ class BaseDocument:
|
||||
"""
|
||||
return session.query(self.sql_model).options(load_only(*fields)).limit(limit).all()
|
||||
|
||||
def get_all_primary_keys(self, session: Session) -> List[str]:
|
||||
def get_all_primary_keys(self, session: Session) -> list[str]:
|
||||
"""Queries the database of the selected model and returns a list
|
||||
of all primary_key values
|
||||
|
||||
@@ -79,7 +79,7 @@ class BaseDocument:
|
||||
|
||||
def get(
|
||||
self, session: Session, match_value: str, match_key: str = None, limit=1, any_case=False
|
||||
) -> BaseModel or List[BaseModel]:
|
||||
) -> Union[BaseModel, list[BaseModel]]:
|
||||
"""Retrieves an entry from the database by matching a key/value pair. If no
|
||||
key is provided the class objects primary key will be used to match against.
|
||||
|
||||
@@ -120,6 +120,8 @@ class BaseDocument:
|
||||
Returns:
|
||||
dict: A dictionary representation of the database entry
|
||||
"""
|
||||
document = document if isinstance(document, dict) else document.dict()
|
||||
|
||||
new_document = self.sql_model(session=session, **document)
|
||||
session.add(new_document)
|
||||
session.commit()
|
||||
@@ -136,6 +138,7 @@ class BaseDocument:
|
||||
Returns:
|
||||
dict: Returns a dictionary representation of the database entry
|
||||
"""
|
||||
new_data = new_data if isinstance(new_data, dict) else new_data.dict()
|
||||
|
||||
entry = self._query_one(session=session, match_value=match_value)
|
||||
entry.update(session=session, **new_data)
|
||||
@@ -144,6 +147,8 @@ class BaseDocument:
|
||||
return self.schema.from_orm(entry)
|
||||
|
||||
def patch(self, session: Session, match_value: str, new_data: dict) -> BaseModel:
|
||||
new_data = new_data if isinstance(new_data, dict) else new_data.dict()
|
||||
|
||||
entry = self._query_one(session=session, match_value=match_value)
|
||||
|
||||
if not entry:
|
||||
@@ -168,8 +173,21 @@ class BaseDocument:
|
||||
session.commit()
|
||||
|
||||
def count_all(self, session: Session, match_key=None, match_value=None) -> int:
|
||||
|
||||
if None in [match_key, match_value]:
|
||||
return session.query(self.sql_model).count()
|
||||
else:
|
||||
return session.query(self.sql_model).filter_by(**{match_key: match_value}).count()
|
||||
|
||||
def _countr_attribute(
|
||||
self, session: Session, attribute_name: str, attr_match: str = None, count=True, override_schema=None
|
||||
) -> Union[int, BaseModel]:
|
||||
eff_schema = override_schema or self.schema
|
||||
# attr_filter = getattr(self.sql_model, attribute_name)
|
||||
|
||||
if count:
|
||||
return session.query(self.sql_model).filter(attribute_name == attr_match).count() # noqa: 711
|
||||
else:
|
||||
return [
|
||||
eff_schema.from_orm(x)
|
||||
for x in session.query(self.sql_model).filter(attribute_name == attr_match).all() # noqa: 711
|
||||
]
|
||||
|
||||
@@ -24,7 +24,23 @@ def init_db(db: Session = None) -> None:
|
||||
|
||||
|
||||
def default_theme_init(session: Session):
|
||||
db.themes.create(session, SiteTheme().dict())
|
||||
default_themes = [
|
||||
SiteTheme().dict(),
|
||||
{
|
||||
"name": "Dark",
|
||||
"colors": {
|
||||
"primary": "#424242",
|
||||
"accent": "#455A64",
|
||||
"secondary": "#00796B",
|
||||
"success": "#43A047",
|
||||
"info": "#1976D2",
|
||||
"warning": "#FF6F00",
|
||||
"error": "#EF5350",
|
||||
},
|
||||
},
|
||||
]
|
||||
for theme in default_themes:
|
||||
db.themes.create(session, theme)
|
||||
|
||||
|
||||
def default_settings_init(session: Session):
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import sqlalchemy as sa
|
||||
import sqlalchemy.orm as orm
|
||||
from mealie.core.config import settings
|
||||
from mealie.db.models.model_base import BaseMixins, SqlAlchemyBase
|
||||
from mealie.db.models.recipe.category import Category, group2categories
|
||||
from sqlalchemy.orm.session import Session
|
||||
from mealie.core.config import settings
|
||||
|
||||
|
||||
class WebhookURLModel(SqlAlchemyBase):
|
||||
@@ -50,10 +50,6 @@ class Group(SqlAlchemyBase, BaseMixins):
|
||||
self.webhook_time = webhook_time
|
||||
self.webhook_urls = [WebhookURLModel(url=x) for x in webhook_urls]
|
||||
|
||||
def update(self, session: Session, *args, **kwargs):
|
||||
|
||||
self.__init__(session=session, *args, **kwargs)
|
||||
|
||||
@staticmethod
|
||||
def get_ref(session: Session, name: str):
|
||||
item = session.query(Group).filter(Group.name == name).one_or_none()
|
||||
|
||||
@@ -27,12 +27,16 @@ class RecipeModel(SqlAlchemyBase, BaseMixins):
|
||||
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)
|
||||
cookTime = 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")
|
||||
@@ -55,12 +59,15 @@ 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")
|
||||
date_added = sa.Column(sa.Date, default=date.today)
|
||||
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)
|
||||
|
||||
@validates("name")
|
||||
def validate_name(self, key, name):
|
||||
assert name != ""
|
||||
@@ -78,6 +85,7 @@ class RecipeModel(SqlAlchemyBase, BaseMixins):
|
||||
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,
|
||||
@@ -85,6 +93,7 @@ class RecipeModel(SqlAlchemyBase, BaseMixins):
|
||||
recipe_category: list[str] = None,
|
||||
tags: list[str] = None,
|
||||
date_added: datetime.date = None,
|
||||
date_updated: datetime.datetime = None,
|
||||
notes: list[dict] = None,
|
||||
rating: int = None,
|
||||
org_url: str = None,
|
||||
@@ -113,6 +122,7 @@ class RecipeModel(SqlAlchemyBase, BaseMixins):
|
||||
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]
|
||||
|
||||
@@ -120,12 +130,15 @@ class RecipeModel(SqlAlchemyBase, BaseMixins):
|
||||
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.date_added = date_added
|
||||
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, *args, **kwargs):
|
||||
"""Updated a database entry by removing nested rows and rebuilds the row through the __init__ functions"""
|
||||
self.__init__(*args, **kwargs)
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import sqlalchemy as sa
|
||||
import sqlalchemy.orm as orm
|
||||
from mealie.db.models.model_base import BaseMixins, SqlAlchemyBase
|
||||
from sqlalchemy.sql.sqltypes import Integer
|
||||
from sqlalchemy import Column, ForeignKey, Integer, String
|
||||
|
||||
|
||||
class SiteThemeModel(SqlAlchemyBase, BaseMixins):
|
||||
__tablename__ = "site_theme"
|
||||
id = sa.Column(Integer, primary_key=True, unique=True)
|
||||
name = sa.Column(sa.String, nullable=False, unique=True)
|
||||
colors = orm.relationship("ThemeColorsModel", uselist=False, cascade="all, delete")
|
||||
id = Column(Integer, primary_key=True, unique=True)
|
||||
name = Column(String, nullable=False, unique=True)
|
||||
colors = orm.relationship("ThemeColorsModel", uselist=False, single_parent=True, cascade="all, delete-orphan")
|
||||
|
||||
def __init__(self, name: str, colors: dict, *arg, **kwargs) -> None:
|
||||
self.name = name
|
||||
@@ -17,12 +16,12 @@ class SiteThemeModel(SqlAlchemyBase, BaseMixins):
|
||||
|
||||
class ThemeColorsModel(SqlAlchemyBase, BaseMixins):
|
||||
__tablename__ = "theme_colors"
|
||||
id = sa.Column(sa.Integer, primary_key=True)
|
||||
parent_id = sa.Column(sa.String, sa.ForeignKey("site_theme.name"))
|
||||
primary = sa.Column(sa.String)
|
||||
accent = sa.Column(sa.String)
|
||||
secondary = sa.Column(sa.String)
|
||||
success = sa.Column(sa.String)
|
||||
info = sa.Column(sa.String)
|
||||
warning = sa.Column(sa.String)
|
||||
error = sa.Column(sa.String)
|
||||
id = Column(Integer, primary_key=True)
|
||||
parent_id = Column(Integer, ForeignKey("site_theme.id"))
|
||||
primary = Column(String)
|
||||
accent = Column(String)
|
||||
secondary = Column(String)
|
||||
success = Column(String)
|
||||
info = Column(String)
|
||||
warning = Column(String)
|
||||
error = Column(String)
|
||||
|
||||
@@ -69,6 +69,9 @@ class RecipeSummary(CamelModel):
|
||||
tags: Optional[list[str]] = []
|
||||
rating: Optional[int]
|
||||
|
||||
date_added: Optional[datetime.date]
|
||||
date_updated: Optional[datetime.datetime]
|
||||
|
||||
class Config:
|
||||
orm_mode = True
|
||||
|
||||
@@ -95,7 +98,6 @@ class Recipe(RecipeSummary):
|
||||
# Mealie Specific
|
||||
settings: Optional[RecipeSettings]
|
||||
assets: Optional[list[RecipeAsset]] = []
|
||||
date_added: Optional[datetime.date]
|
||||
notes: Optional[list[RecipeNote]] = []
|
||||
org_url: Optional[str] = Field(None, alias="orgURL")
|
||||
extras: Optional[dict] = {}
|
||||
|
||||
@@ -8,8 +8,8 @@ class Colors(BaseModel):
|
||||
accent: str = "#00457A"
|
||||
secondary: str = "#973542"
|
||||
success: str = "#43A047"
|
||||
info: str = "#4990BA"
|
||||
warning: str = "#FF4081"
|
||||
info: str = "#1976D2"
|
||||
warning: str = "#FF6F00"
|
||||
error: str = "#EF5350"
|
||||
|
||||
class Config:
|
||||
|
||||
Reference in New Issue
Block a user