КиндЕррор в Google App Engine

#python #google-app-engine

#python #google-app-engine

Вопрос:

Я определил простой класс в GAE для хранения данных профилей пользователей следующим образом:

 class User(db.Model):
    email = db.EmailProperty()
    role = db.StringProperty(default=roles.USER)
    first_name = db.StringProperty()
    last_name = db.StringProperty()
...
  

Я использую memcache для хранения информации о сеансе. данные memcache выглядят следующим образом { 'key': 'agpjYW5kaXJhdGVzcgoLEgRVc2VyGCMM'} . Я получаю session_id значение из файла cookie. Когда я пытаюсь связать информацию о пользователе с этим файлом cookie следующим образом:

 session_id = request['session_id']
data = memcache.get(session_id)
user = User.get(data['key'])
  

Я получаю KindError исключение:

 KindError: Kind 'User' is not a subclass of kind 'User'
  

Я знаю, что этот пользователь существует, memcache существует. Пользовательский класс определен только один раз в моем проекте. Почему возникает эта ошибка и как я могу заставить ее работать?

ОБНОВЛЕНИЕ: я попытался использовать db.get() вместо User.get() , и это сработало. Итак, в чем может быть проблема?

Ответ №1:

Model.get() проверяет, имеет ли предоставленный ключ правильный вид, как определено в документации. Если не правильный вид, он выдаст KindError .

db.get() не выполняет никакой проверки типов и, следовательно, успешно выполнит предоставленное значение, если оно существует в хранилище данных, но не обязательно вернет объект User.

Итак, вам нужно проверить, действительно ли ключ в вашем memcache имеет User вид. Вы уверены, что в какой-то момент он не перезаписан ключом другой модели?

Комментарии:

1. Похоже, что проблема связана с импортом. В разных модулях я использовал разные операторы импорта. Один использовался из lib.utils.profiles для импорта пользователя, и он работал хорошо, поскольку содержит весь путь к модулю. Другой используемый из utils.profiles импорт пользователя, и он выдал исключение.

Ответ №2:

Платформа App Engine определяет класс с именем «User» как часть пользовательского API. Кроме того, у вас есть свой собственный класс с тем же именем. Когда возникает исключение, вы пытаетесь использовать одно, но получаете другое.

Чтобы избежать этого, переименуйте свою модель. Вы также должны быть осторожны при импорте модулей в Python. Вместо:

 from google.appengine.api.users import User
  

или хуже:

 from google.appengine.api.users import *
  

вы должны использовать:

 from google.appengine.api import users
  

А затем обратитесь к users.User , что является однозначным.

Комментарии:

1. Это очень полезные заметки. Я обновлю свой код в соответствии с вашими советами. Спасибо!

Ответ №3:

Проблема, как мне кажется, более тонкая, чем эта. Я получал ошибку при этом вызове Model.get() (я извлекаю одноэлементный объект верхнего уровня, который всегда присутствует):

 datastore = GDSDatastore.get(gds.Key.from_path(*path))
  

итак, я исследовал этот код:

 datastore = gds.get(gds.Key.from_path(*path))
if not(datastore is None or isinstance(datastore, GDSDatastore)):
    logger.error("KindError isinstance(GDSDatastore)=%s class=%s" % (isinstance(datastore, GDSDatastore), datastore.__class__.__name__))
    raise gds.KindError('Kind %r is not a GDSDatastore instance' %
                    (datastore.kind()))
  

В подавляющем большинстве случаев я не получаю ошибок, но сегодня я получил этот интересный журнал:

 KindError isinstance(GDSDatastore)=False class=GDSDatastore
  

Теперь это кажется мне довольно странным.

(Примечание: GDSDatastore определяется локально: класс GDSDatastore(gds.Model))