【发布时间】:2013-04-03 06:41:48
【问题描述】:
我的模型 User 和属性 username 带有验证器,用于验证 username 的可用字符、非空字符和 存在 在数据库中。因此,例如,在处理注册表单时,我不需要任何其他检查 - 我只需将表单的 username 值分配给模型的属性,并在输入 username 时捕获验证错误已经存在...
但是,这行不通。
因为 NDB 也会验证属性的比较参数(请参阅 ndb/model.py 中的 Property._comparison 方法),并且它会在 Query.filter(User.username == [somevalue]) 中进行无休止的请求,最后引发RuntimeError: maximum recursion depth exceeded。 NDB 尝试使用 validate_username 验证 [somevalue] 并一次又一次地转到此查询...
可以将用户名分配给实体的ID并使用User.get_by_id(),但需要username才能更改,所以我需要使用Query.get()。
所以这是我的User 模型:
class User(ndb.Model):
def validate_username(self, value):
value = str(value).strip()
# Other useful checks - length, available symbols, etc
if User.get_user(value):
raise ValueError('Username already exists')
return value
@classmethod
def get_user(cls, username):
username = str(username)
user_q = User.query()
user_q = user_q.filter(User.username == username) # Here is the problem
return user_q.get()
username = ndb.StringProperty(validator=validate_username)
例如:
# Trying to add user, get RuntimeError exception
u = User()
u.username = 'John'
我做错了什么?解决此类问题的最佳方法是什么?
更新到Tim Hoffman:
谢谢。是的,我错过了 prop 参数,但是方法在 self 和 val 在 val 参数中收到了 prop - 因此我没有提到这个错误。但是,您错过了关键问题 - 您没有在验证器中使用带有过滤器的查询(User.get_user 方法)。试试这个,有没有感觉函数或者方法验证器是:
def validate_username2(prop, value):
if User.get_user(value):
raise Exception('User exists!')
return value
class User(ndb.Model):
def validate_username(self, value):
if User.get_user(value):
raise Exception('User exists!')
return value
@classmethod
def get_user(self, username):
user_q = User.query()
user_q = user_q.filter(User.username == username)
return user_q.get()
# Try both please
username = ndb.StringProperty(validator=validate_username)
#username = ndb.StringProperty(validator=validate_username2)
【问题讨论】:
-
文档说 - 将使用参数 (prop, value) 调用,并且应该返回(可能是强制的)值或引发异常。但是,您的 validate_username 方法仅使用值定义。尝试将其定义为函数而不是带有 args(属性、值)的方法。
标签: python google-app-engine app-engine-ndb