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