Open simonprickett opened 2 years ago
Guess I didn't test that well enough!
You're right, a strict field will have trouble reading strings from Redis.
To use strict fields, you'd want to have two models -- one for creating data (when you'd want to check the incoming values) and one for reading data from redis. Like this:
import abc
from redis_om import HashModel
from pydantic import StrictInt, ValidationError
class AdoptableBase(HashModel, abc.ABC):
name: str
species: str
weight: float
description: str
class ReadAdoptable(AdoptableBase):
age: int
class Meta:
model_key_prefix = "adoptable"
class WriteAdoptable(AdoptableBase):
age: StrictInt
class Meta:
model_key_prefix = "adoptable"
try:
fido = WriteAdoptable(
name = "Fido",
species = "dog",
age = 3,
weight = 37.2,
description = "Fido is a fantastic dog in need of a new home"
)
print(fido.key())
print("Saving Fido...")
fido.save()
print("Retrieving Fido...")
an_adoptable = ReadAdoptable.get(fido.pk)
print(an_adoptable)
except ValidationError as e:
print(e)
It's a little annoying that a model doesn't inherit the model_key_prefix
from its parent class's Meta class. It probably should, for cases like this. If it did, the models would be less verbose:
class AdoptableBase(HashModel, abc.ABC):
name: str
species: str
weight: float
description: str
class ReadAdoptable(AdoptableBase):
age: int
class WriteAdoptable(AdoptableBase):
age: StrictInt
NOTE: With Pydantic (the validation library under this stuff), you can't just subclass a class and override a single property, so we need a base class here and two subclasses.
And for reference, here is the code that unsets model_key_prefix
if a subclass gets it from a parent: https://github.com/redis/redis-om-python/blob/3a3ed91ed03732789cca12b6ca3aed6cb5c5467b/aredis_om/model/model.py#L1029
This logic should probably be:
Oh, there's also the construct()
method: https://pydantic-docs.helpmanual.io/usage/models/#creating-models-without-validation
I didn't go that route, but we could treat the data in Redis as already validated when we pull it back out. This probably makes sense. The only thing is, we'd need to test if that will coerce the values to their expected types, like parse_obj() does.
Here's one of the usages of parse_obj(): https://github.com/redis/redis-om-python/blob/3a3ed91ed03732789cca12b6ca3aed6cb5c5467b/aredis_om/model/model.py#L1326
I've created a basic model and set an int field to be
StrictInt
... this saves to Redis fine, but fails on retrieval... I imagine because this is really stored as a string in Redis.Example code:
Running this yields:
Python version:
redis-om-python version:
I was using this as a guide: https://github.com/redis/redis-om-python/blob/main/docs/getting_started.md#strict-validation