Closed ID2343242 closed 6 months ago
I have just tried using find on this same Document and it throws the same validation error. So currently I can only get insert to work with a Document containing a Decimal field.
Hi! Thank you for the catch. I'll check and fix it this/next week.
@ID2343242 try replacing the Decimal
field annotation with beanie.DecimalAnnotation
.
@ID2343242 try replacing the
Decimal
field annotation withbeanie.DecimalAnnotation
.
thank brocha
Hi @ID2343242 ,
Could you please try beanie.DecimalAnnotation
?
I came up with this solution using a decorator:
from typing import Any, Callable, TypeVar, cast
import bson
from pydantic import BaseModel, create_model, model_validator
T = TypeVar("T", bound="BaseModel")
def beanie_decimal(*fields: str) -> Callable[[type[T]], type[T]]:
def validator(cls: type[T], v: Any) -> Any:
for f in (f.split(".") for f in fields):
current = v
while (field := f.pop(0)) and current:
if not len(f):
if value := current.get(field, None):
current[field] = (
value.to_decimal()
if isinstance(value, bson.Decimal128)
else value
)
break
current = current.get(field, None)
return v
def decorator(model: type[T]) -> type[T]:
return create_model(
model.__name__,
__base__=model,
__module__=model.__module__,
__validators__={
"beanie_decimal": cast(
classmethod, model_validator(mode="before")(validator)
)
},
)
return decorator
@beanie_decimal("price")
class Product(Document):
name: str
price: Decimal = Field(decimal_places=3)
product = Product(name="Apple", price=Decimal('1.99'))
await product.save()
The decorator supports multiple fields being passed in and allows you to define nested model paths.
This issue is stale because it has been open 30 days with no activity.
This issue was closed because it has been stalled for 14 days with no activity.
Describe the bug When using a Decimal type in a class as below, the insert works fine, the save also adds the Document to the database but it throws a ValidationError as shown below.
To Reproduce
class Product(Document): name: str price: Decimal = Field(decimal_places=3) product = Product(name="Apple", price=Decimal('1.99')) await product.save()
Expected behavior The save function should not throw the validation exception and if the Document does not exist should operate in the same way as insert.
Additional context Exception has occurred: ValidationError 1 validation error for Product price Decimal input should be an integer, float, string or Decimal object [type=decimal_type, input_value=Decimal128('1.99'), input_type=Decimal128] For further information visit https://errors.pydantic.dev/2.3/v/decimal_type File "/test.py", line 120, in main await product.save() File "/test.py", line 126, in
asyncio.run(main())
pydantic_core._pydantic_core.ValidationError: 1 validation error for Product
price
Decimal input should be an integer, float, string or Decimal object [type=decimal_type, input_value=Decimal128('1.99'), input_type=Decimal128]
For further information visit https://errors.pydantic.dev/2.3/v/decimal_type