0

我有带有验证器的模型User和属性,用于验证数据库中的可用字符、非空字符和存在。因此,例如,在处理注册表单时,我不需要任何其他检查 - 我只需将表单的值分配给模型的属性并捕获验证错误(如果输入已经存在)...usernameusernameusernameusername

但是,这行不通。

因为 NDB 也验证了属性的比较参数(请参阅 ndb/model.py 中的 Property._comparison 方法),并且它在 Query.filter(User.username == [somevalue]) 中进行无休止的请求,最后引发RuntimeError: maximum recursion depth exceeded. NDB 尝试验证 [somevalue]validate_username并一次又一次地转到此查询...

可以将用户名分配给实体的 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'

我做错了什么?解决此类问题的最佳方法是什么?

更新到蒂姆霍夫曼 谢谢。是的,我错过了 prop 参数,但是在参数propself和参数中收到了方法 - 因此我没有提到这个错误。但是,您错过了关键问题 - 您没有在验证器中使用带有过滤器的查询(User.get_user 方法)。试试这个,没有感觉函数或方法验证器是:valval

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)
4

1 回答 1

2

我相信您的问题是由于错误地将您的验证器定义为一种方法并且不接受正确的参数。请参阅下面的快速示例,确实可以使用过滤器。

The db, ndb, users, urlfetch, and memcache modules are imported.
dev~cash-drawer> def vla(prop,val):
...    if val == "X":
...      raise ValueError
...    return val
... 
dev~cash-drawer> 
dev~cash-drawer> 
dev~cash-drawer> class X(ndb.Model):
...    name = ndb.StringProperty(validator=vla)
... 
dev~cash-drawer> y = X()
dev~cash-drawer> y.name = "X"
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/home/timh/google_appengine/google/appengine/ext/ndb/model.py", line 1258, in __set__
    self._set_value(entity, value)
  File "/home/timh/google_appengine/google/appengine/ext/ndb/model.py", line 1004, in _set_value
    value = self._do_validate(value)
  File "/home/timh/google_appengine/google/appengine/ext/ndb/model.py", line 953, in _do_validate
    newvalue = self._validator(self, value)
  File "<console>", line 3, in vla
ValueError
dev~cash-drawer> y.name = "aaa"
dev~cash-drawer> y.put()
Key('X', 5060638606280884224)
dev~cash-drawer> z=X.query().filter(X.name == "aaa")
dev~cash-drawer> list(z)
[X(key=Key('X', 5060638606280884224), name=u'aaa')]

    dev~cash-drawer> z=X.query().filter(X.name == "X")
    Traceback (most recent call last):
        File "<console>", line 1, in <module>
        File "/home/timh/google_appengine/google/appengine/ext/ndb/model.py", line 859, in __eq__
        return self._comparison('=', value)
        File "/home/timh/google_appengine/google/appengine/ext/ndb/model.py", line 847, in _comparison
        value = self._do_validate(value)
         File "/home/timh/google_appengine/google/appengine/ext/ndb/model.py", line 953, in _do_validate
        newvalue = self._validator(self, value)
         File "<console>", line 3, in vla
    ValueError
    dev~cash-drawer> 
于 2013-04-03T12:17:26.323 回答