Remove all sqlalchemy lazy-loading from app (#2260)

* Remove some implicit lazy-loads from user serialization

* implement full backup restore across different database versions

* rework all custom getter dicts to not leak lazy loads

* remove some occurances of lazy-loading

* remove a lot of lazy loading from recipes

* add more eager loading
remove loading options from repository
remove raiseload for checking

* fix failing test

* do not apply loader options for paging counts

* try using selectinload a bit more instead of joinedload

* linter fixes
This commit is contained in:
Sören
2023-03-24 17:27:26 +01:00
committed by GitHub
parent fae62ecb19
commit 4b426ddf2f
23 changed files with 351 additions and 142 deletions

View File

@@ -28,7 +28,9 @@ class IngredientUnitModel(SqlAlchemyBase, BaseMixins):
abbreviation: Mapped[str | None] = mapped_column(String)
use_abbreviation: Mapped[bool | None] = mapped_column(Boolean, default=False)
fraction: Mapped[bool | None] = mapped_column(Boolean, default=True)
ingredients: Mapped[list["RecipeIngredient"]] = orm.relationship("RecipeIngredient", back_populates="unit")
ingredients: Mapped[list["RecipeIngredientModel"]] = orm.relationship(
"RecipeIngredientModel", back_populates="unit"
)
@auto_init()
def __init__(self, **_) -> None:
@@ -45,7 +47,9 @@ class IngredientFoodModel(SqlAlchemyBase, BaseMixins):
name: Mapped[str | None] = mapped_column(String)
description: Mapped[str | None] = mapped_column(String)
ingredients: Mapped[list["RecipeIngredient"]] = orm.relationship("RecipeIngredient", back_populates="food")
ingredients: Mapped[list["RecipeIngredientModel"]] = orm.relationship(
"RecipeIngredientModel", back_populates="food"
)
extras: Mapped[list[IngredientFoodExtras]] = orm.relationship("IngredientFoodExtras", cascade="all, delete-orphan")
label_id: Mapped[GUID | None] = mapped_column(GUID, ForeignKey("multi_purpose_labels.id"), index=True)
@@ -57,7 +61,7 @@ class IngredientFoodModel(SqlAlchemyBase, BaseMixins):
pass
class RecipeIngredient(SqlAlchemyBase, BaseMixins):
class RecipeIngredientModel(SqlAlchemyBase, BaseMixins):
__tablename__ = "recipes_ingredients"
id: Mapped[int] = mapped_column(Integer, primary_key=True)
position: Mapped[int | None] = mapped_column(Integer, index=True)
@@ -92,16 +96,16 @@ class RecipeIngredient(SqlAlchemyBase, BaseMixins):
self.orginal_text = unidecode(orginal_text).lower().strip()
@event.listens_for(RecipeIngredient.note, "set")
def receive_note(target: RecipeIngredient, value: str, oldvalue, initiator):
@event.listens_for(RecipeIngredientModel.note, "set")
def receive_note(target: RecipeIngredientModel, value: str, oldvalue, initiator):
if value is not None:
target.name_normalized = unidecode(value).lower().strip()
else:
target.name_normalized = None
@event.listens_for(RecipeIngredient.original_text, "set")
def receive_original_text(target: RecipeIngredient, value: str, oldvalue, initiator):
@event.listens_for(RecipeIngredientModel.original_text, "set")
def receive_original_text(target: RecipeIngredientModel, value: str, oldvalue, initiator):
if value is not None:
target.original_text_normalized = unidecode(value).lower().strip()
else:

View File

@@ -17,7 +17,7 @@ from .api_extras import ApiExtras, api_extras
from .assets import RecipeAsset
from .category import recipes_to_categories
from .comment import RecipeComment
from .ingredient import RecipeIngredient
from .ingredient import RecipeIngredientModel
from .instruction import RecipeInstruction
from .note import Note
from .nutrition import Nutrition
@@ -77,10 +77,10 @@ class RecipeModel(SqlAlchemyBase, BaseMixins):
)
tools: Mapped[list["Tool"]] = orm.relationship("Tool", secondary=recipes_to_tools, back_populates="recipes")
recipe_ingredient: Mapped[list[RecipeIngredient]] = orm.relationship(
"RecipeIngredient",
recipe_ingredient: Mapped[list[RecipeIngredientModel]] = orm.relationship(
"RecipeIngredientModel",
cascade="all, delete-orphan",
order_by="RecipeIngredient.position",
order_by="RecipeIngredientModel.position",
collection_class=ordering_list("position"),
)
recipe_instructions: Mapped[list[RecipeInstruction]] = orm.relationship(
@@ -173,7 +173,7 @@ class RecipeModel(SqlAlchemyBase, BaseMixins):
self.recipe_instructions = [RecipeInstruction(**step, session=session) for step in recipe_instructions]
if recipe_ingredient is not None:
self.recipe_ingredient = [RecipeIngredient(**ingr, session=session) for ingr in recipe_ingredient]
self.recipe_ingredient = [RecipeIngredientModel(**ingr, session=session) for ingr in recipe_ingredient]
if assets:
self.assets = [RecipeAsset(**a) for a in assets]