Ошибка типа при использовании хранилища данных GAE и пространств имен — не удается извлечь сущность

#python #google-app-engine #namespaces

#python #google-app-engine #пространства имен

Вопрос:

Я пытаюсь восстановить некоторую информацию OAuth, которую я сохранил с помощью хранилища данных, но я получаю эту ошибку при создании экземпляра моего класса OAuthConsumer:

 TypeError: __init__() got an unexpected keyword argument 'consumer_secret'
  

Я также впервые экспериментирую с пространством имен, и мне интересно, имеет ли это какое-то отношение к этому. Класс выглядит следующим образом:

 creds = OAuthConsumer('google')

class OAuthConsumer(db.Model):
    '''the oauth consumer information'''
    consumer_key = db.StringProperty()
    consumer_secret = db.StringProperty()

    def __init__(self, service):
        namespace_manager.set_namespace(service)
        query = db.GqlQuery('SELECT * FROM OAuthConsumer')
        creds = query.get()
        self.consumer_key = creds.consumer_key
        self.consumer_secret = creds.consumer_secret
  

Вот что я получил, используя средство просмотра данных:

учетные данные заблокированы

Есть идеи относительно того, что я делаю неправильно?

Ответ №1:

Вы переопределяете __init__ метод в классе модели хранилища данных и не передаете аргументы ключевого слова родительскому конструктору (или вообще не вызываете его!).

Как общее правило, вы не должны переопределять конструктор класса модели хранилища данных. Можно сделать это правильно, но это сложно, и гораздо безопаснее предоставить метод класса в виде фабрики, например:

 class OAuthConsumer(db.Model):
    '''the oauth consumer information'''
    consumer_key = db.StringProperty()
    consumer_secret = db.StringProperty()

    @classmethod
    def new(cls, service):
        namespace_manager.set_namespace(service)
        query = db.GqlQuery('SELECT * FROM OAuthConsumer')
        creds = query.get()
        return cls(consumer_key=creds.consumer_key, consumer_secret=creds.consumer_secret)

creds = OAuthConsumer('google')
  

Ваш код более чем немного странный по нескольким причинам, хотя:

  • При создании нового экземпляра вы извлекаете и копируете поля из другого (фактически) случайно выбранного экземпляра той же модели!
  • Вы устанавливаете пространство имен внутри конструктора (или в переписанной версии, в заводском методе). Пространство имен является глобальным параметром, и вам действительно не следует делать это внутри библиотечного метода. Впоследствии вы также не устанавливаете его обратно.

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

1. Потрясающе, большое спасибо за комментарии. Я все еще получаю представление о том, как обращаться с GAE, а также с классами и функциями, так что это огромная помощь!