'SQLAlchemy implicit type conversion and Date validation
Let's assume this model class:
class Person(db.Model):
__tablename__ = "person"
date_of_birth = db.Column(db.Date)
With person
being an instance of Person
, I can do the following in my unit test:
person.date_of_birth = "05/05/2000"
So far, so good, and this code has been in production for some time. Now someone reports a bug that there are persons with dates of birth in the future. Dates of birth in the future are invalid in my context and I want to prevent them from entering the data store, so I add a validator to the model class:
@validates("date_of_birth")
def validate_date_of_birth(self, key, date_of_birth):
if date_of_birth and date_of_birth > datetime.now().date():
raise BirthDayException("A date of birth must not be in the future.")
return date_of_birth
This will, somewhat understandably, break my unit test and throw an exception when I do the assignment from above:
> if date_of_birth and date_of_birth > datetime.datetime.now().date():
E TypeError: '>' not supported between instances of 'str' and 'datetime.date'
I don't quite understand where I should address it, though.
- Should I change my unit test and not assign a string value to a date property? But there could be other places in the code where this is happening, leaving me exposed to regression.
- Or should I check for the correct data type in the validator and convert it if necessary?
- Or can I somehow tell SqlAlchemy to do the auto-conversion that it normally does BEFORE the validator is invoked? That would be the nicest solution.
Thanks for your input.
Solution 1:[1]
Fwiw, I ended up doing the unthinkable - check for the type and convert to date if it is a string:
if type(date_of_birth) is str:
date_of_birth = datetime.datetime.strptime(date_of_birth, "%m/%d/%Y").date()
if date_of_birth and date_of_birth > datetime.datetime.now().date():
raise BirthDayException("A date of birth must not be in the future.")
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | cdonner |