Reputation: 4306
I'm building a form-based app with Flask, and ran into a problem with an optional email field.
Is there any way around setting a datastore field of type EmailProperty()
and allowing it to be empty? It seems that even with required=False
in the entity definition, it still raises BadValueError
saying the field must not be empty
.
# my entity definition
from google.appengine.ext import db
class Model(db.Model):
email = db.EmailProperty(required=False)
In the latest few versions of the Python client, in google_appengine/google/appengine/api/datastore_types.py
around line 879, the __init__
call of the Email class looks like this:
class Email(unicode):
def __init__(self, email):
super(Email, self).__init__()
ValidateString(email, 'email')
It passes execution over to ValidateString which has an empty_ok boolean parameter which defaults to False
:
def ValidateString(value,
name='unused',
exception=datastore_errors.BadValueError,
max_len=_MAX_STRING_LENGTH,
empty_ok=False):
It'd be nice if the get set to the inverse of whatever my EmailProperty
field's required=
param is set to. For example, in my entity definition, since I have required=False
it'd be nice if this Email class could pass True
into the empty_ok
parameter when calling ValidateString()
. However, since it doesn't, I'd really like to figure out a good workaround.
I can't be the only developer out there who's ever tried to store an optional email address field? If data gets passed on my form, I still want the built-in validations to run, so I don't want to change to a StringProperty
if I can help it...
Upvotes: 0
Views: 153
Reputation: 1341
N.B.: The db module has long since been superseded by the ndb module. db hasn't received any significant update in years. I really recommend updating if possible, but that notwithstanding here's some ideas to work around it.
As you've ascertained, the Email
class won't allow an empty value. Likely the easiest thing to do here is just define your own type class and property class to use in place of EmailProperty
:
from google.appengine.ext import db
class EmailOrNone(datastore_types.Email):
def __init__(self, email):
super(EmailOrNone, self).__init__(email)
ValidateString(email, 'email', empty_ok=True)
class EmailOrNoneProperty(db.EmailProperty):
data_type = EmailOrNone
Then just use the new EmailOrNoneProperty
in place of EmailProperty
.
You could also just use a StringProperty
with a custom validator.
Disclaimer: I have not tested this code, but the idea is sound.
Upvotes: 1
Reputation: 1222
How about only calling the validation function if an email was provided?
class Email(unicode):
def __init__(self, email):
super(Email, self).__init__()
if email != "":
ValidateString(email, 'email')
Note I've deliberately gone for if email != ""
rather than the more pythonic if email
so that if a user provides a non-empty "email" that evaluates as False
, it won't result in skipping the string validation.
Upvotes: 0