fix: Pydantic Serialization Issues (#3157)

* replaced pydantic inits with validators

* fixed serialization dropping food and unit ids
This commit is contained in:
Michael Genson 2024-02-11 17:34:56 -06:00 committed by GitHub
parent 67313f8f03
commit df75cb4034
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 16 additions and 20 deletions

View File

@ -2,7 +2,7 @@ from __future__ import annotations
from datetime import datetime
from pydantic import UUID4, ConfigDict, field_validator
from pydantic import UUID4, ConfigDict, field_validator, model_validator
from sqlalchemy.orm import joinedload, selectinload
from sqlalchemy.orm.interfaces import LoaderOption
@ -100,14 +100,15 @@ class ShoppingListItemOut(ShoppingListItemBase):
created_at: datetime | None = None
update_at: datetime | None = None
def __init__(self, **kwargs):
super().__init__(**kwargs)
@model_validator(mode="after")
def post_validate(self):
# if we're missing a label, but the food has a label, use that as the label
if (not self.label) and (self.food and self.food.label):
self.label = self.food.label
self.label_id = self.label.id
return self
model_config = ConfigDict(from_attributes=True)
@classmethod

View File

@ -6,7 +6,7 @@ from pathlib import Path
from typing import Annotated, Any, ClassVar
from uuid import uuid4
from pydantic import UUID4, BaseModel, ConfigDict, Field, field_validator
from pydantic import UUID4, BaseModel, ConfigDict, Field, field_validator, model_validator
from pydantic_core.core_schema import ValidationInfo
from slugify import slugify
from sqlalchemy import Select, desc, func, or_, select, text
@ -183,17 +183,8 @@ class Recipe(RecipeSummary):
model_config = ConfigDict(from_attributes=True)
@classmethod
def model_validate(cls, obj):
recipe = super().model_validate(obj)
recipe.__post_init__()
return recipe
def __init__(self, **kwargs) -> None:
super().__init__(**kwargs)
self.__post_init__()
def __post_init__(self) -> None:
@model_validator(mode="after")
def post_validate(self):
# the ingredient disable_amount property is unreliable,
# so we set it here and recalculate the display property
disable_amount = self.settings.disable_amount if self.settings else True
@ -202,6 +193,8 @@ class Recipe(RecipeSummary):
ingredient.is_food = not ingredient.disable_amount
ingredient.display = ingredient._format_display()
return self
@field_validator("slug", mode="before")
def validate_slug(slug: str, info: ValidationInfo):
if not info.data.get("name"):

View File

@ -6,7 +6,7 @@ from fractions import Fraction
from typing import ClassVar
from uuid import UUID, uuid4
from pydantic import UUID4, ConfigDict, Field, field_validator
from pydantic import UUID4, ConfigDict, Field, field_validator, model_validator
from sqlalchemy.orm import joinedload
from sqlalchemy.orm.interfaces import LoaderOption
@ -31,6 +31,7 @@ def display_fraction(fraction: Fraction):
class UnitFoodBase(MealieModel):
id: UUID4 | None = None
name: str
plural_name: str | None = None
description: str = ""
@ -134,9 +135,8 @@ class RecipeIngredientBase(MealieModel):
Automatically calculated after the object is created, unless overwritten
"""
def __init__(self, **kwargs) -> None:
super().__init__(**kwargs)
@model_validator(mode="after")
def post_validate(self):
# calculate missing is_food and disable_amount values
# we can't do this in a validator since they depend on each other
if self.is_food is None and self.disable_amount is not None:
@ -151,6 +151,8 @@ class RecipeIngredientBase(MealieModel):
if not self.display:
self.display = self._format_display()
return self
@field_validator("unit", mode="before")
@classmethod
def validate_unit(cls, v):