Google App Engine и Python и объекты, которые передаются по значению - PullRequest
2 голосов
/ 19 сентября 2009

Это на самом деле вопрос языка Python, но он обернут вокруг конкретной проблемы Google appengine.

У нас есть

class User( db.Model ) :
  email = db.StringProperty()
  name = db.StringProperty()
  password = db.StringProperty()
  # more fields..

Поскольку к учетной записи пользователя обращаются так часто, мы сохраняем копию в сеансе, используя gaeutilities (в качестве дополнительного вопроса: это плохо для GAE? Я думал, что уменьшу ДБ немного.)

class UpdateProfile( webapp.RequestHandler ):
  def post( self ):
    # User posting update to his name
    self.session = sessions.Session()

    #######
    # way#1: update the copy of the User object in SESSION, then .put() it
    self.session[ 'current_user' ].name = self.request.get( 'name' )
    self.session[ 'current_user' ].put()
    # does not work.
    #######

    #######
    # way#2: make a copy of the User object in SESSION, then .put() it
    user = self.session[ 'current_user' ]
    user.name = self.request.get( 'name' )
    user.put()
    # works to update the datastore, but the copy of user in self.session
    # is NOT UPDATED!  <b>I thought Python was
    # pass-by-reference.</b>  It is when you work with lists anyway.
    # Why isn't it "acting right" with this type of object??
    #######


    #######
    # way#3: way that works.
    user = self.session[ 'current_user' ]
    user.name = self.request.get( 'name' )
    user.put()
    self.session[ 'current_user' ] = user
    # works completely
    #######

Что происходит в каждом из этих 3 случаев? Почему не работают случаи 1 и 2?

Ответы [ 3 ]

3 голосов
/ 19 сентября 2009

Я предполагаю:

Помещение объектов в сессию означает, что объекты сериализуются (обычно обрабатываются) и где-то хранятся (диск, память, дБ). Когда он извлекается из сеанса, объект new создается из сериализованного старого состояния.

  • В первом примере каждый self.session[ 'current_user' ] дает вам новый объект, один из которых вы обновляете, а другой сохраняется в БД.
  • Во втором вы получите один объект, сохраните его в БД, но не в сеансе.

Кстати, Python делает «вызов через обмен», но это не имеет никакого отношения к вашей проблеме; -)

2 голосов
/ 22 сентября 2009

Я автор gautilities. Я связался с Ником, чтобы поговорить об этом, и он дал мне несколько хороших идей. У меня будет решение для этого в финальной версии 1.3.

1 голос
/ 23 сентября 2009

Извините, я новичок на этом сайте и не вижу, где комментировать ответ?

Во всяком случае, я исправил конкретную проблему, которая спровоцировала оригинальный пост. Хотя сериализация данных все еще неоптимальна, что происходит при записи, мне удалось убедиться, что назначение объектов модели в качестве элементов в сеансе будет работать так, как ожидалось. Вместо того, чтобы переписывать сериализацию (это было бы серьезным переписыванием), я вместо этого решил определить, когда модель вставляется как элемент данных сеанса, и установить для него свойство ReferenceProperty. Это означает, что объектам модели вообще не нужно накладываться на сериализацию.

Если объект, с которым связан ReferenceProperty, удаляется, ReferenceProperty в сеансе будет удален при попытке его загрузки. Это означает, что вам придется перехватывать исключения, такие как KeyError, которые вызываются Session, как должен делать словарь. Я надеюсь, что это достаточно интуитивно понятно, но я открыт для любых комментариев Я проверю эту страницу снова несколько раз в течение следующих нескольких недель.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...