2013-04-03 2 views
0

У меня есть модель User и свойство username с валидатор, который проверяет username доступных символов, не пусто и существование в БД. Таким образом, я не нуждаюсь в каких-либо других проверках при обращении с регистрационной формой, например, я просто присвоил значение формы username для свойства модели и ошибки проверки ловушки, если введено username.запросов фильтрации по недвижимости с валидатора выставиться

Но это не работает.

Поскольку NDB также проверяет аргументы сравнения свойств (см. Метод Property._comparison в ndb/model.py), и он переходит к бесконечной рекурсии в 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' 

Что я делаю неправильно? Каков наилучший способ решения такой проблемы?

ОБНОВЛЕНИЕ ДО Tim Hoffman: Спасибо. Да, я пропустил аргумент prop, но метод получил prop в self и val в val аргументах - таким образом, я не упомянул об этой ошибке. Но вы пропустили ключевую проблему - вы не используете запрос с фильтром в validator (метод 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) 
+0

Документы говорят - будут вызываться с аргументами (prop, value) и должны либо вернуть (возможно принудительное) значение, либо вызвать исключение. Однако ваш метод validate_username определяется только значением. Попробуйте определить его как функцию, а не метод с args (свойство, значение). –

ответ

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> 
+0

Да, я пропустил аргумент 'prop', но метод получил' prop' в 'self' и' val' в 'val' аргументах, поэтому я не упомянул об этой ошибке. Но вы пропустили ключевую проблему - вы не используете запрос с фильтром в валидаторе. Попробуйте это, нет никакой функции определения смысла или метода: [я добавил код к основному вопросу, так как комментарии разбивают строки] – Denisigo

+0

Согласовано, но если вы посмотрите на мой пример, я выполняю запрос на модели с валидатором это работает. На самом деле, я просто запускаю тест с примером, который я предоставил, и валидатор выполняет поиск по запросу. Таким образом, вы можете видеть, что выше значение ошибки возникает, если я запрашиваю что-то, что не проходит валидатор. Это имеет смысл, и в вашем случае валидатор вызывается сам, следовательно, рекурсия. Я когда-либо пытался обновить объект, вы также получите ошибку, так как проверка подлинности будет запущена снова и завершится с ошибкой. Я думаю, вы должны использовать фабричный метод для создания/проверки дубликата –

+0

Да, я понял, что ваш пример и мои работы похожи, пока я не добавлю query.filter в validator.Я не могу понять одно: почему NDB проверяет значения в операторе уравнения? Не выполнять запрос, если значение заведомо неверно? – Denisigo

Смежные вопросы