Как представить отношения один-к-одному в App Engine - PullRequest
3 голосов
/ 07 июня 2011

Скажем, у вас есть понятие "пользовательских" записей, которые вы хотели бы хранить в хранилище данных.

class User (db.Model):
  first_name = db.StringProperty()
  last_name = db.StringProperty()
  created = db.DateTimeProperty(auto_now_add=True)
  twitter_oauth_token = db.StringProperty()
  twitter_oauth_secret = db.StringProperty()

Есть некоторые поля, которые вы хотели бы использовать почти каждый раз, когда используете пользовательский объект, например first_name и last_name.

Однако есть некоторые поля, у которых есть только один вариант использования, например, twitter_oauth_token и twitter_oauth_secret, и несколько неэффективно использовать их для сериализации и десериализации, когда они не нужны в 95% случаев.

Итак, если вы разделите свою модель на:

class User (db.Model):
  first_name = db.StringProperty()
  last_name = db.StringProperty()
  created = db.DateTimeProperty(auto_now_add=True)

class UserTwitterOauth(db.Model):
  oauth_token = db.StringProperty(required=True)
  oauth_secret = db.StringProperty(required=True)
  created = db.DateTimeProperty(auto_now_add=True)

Вы можете поместить ReferenceProperty для Пользователя в UserTwitterOauth, но на самом деле это будет один-ко-многим, поскольку ничто не останавливается на том, чтобы быть несколькими объектами UserTwitterOauth на Пользователя. Вы хотите, чтобы не более одного UserTwitterOauth было связано с любым пользователем. Как вы можете связать эти модели один на один?

Ответы [ 2 ]

6 голосов
/ 08 июня 2011

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

my_user = User(first_name="John", last_name="Smith")
my_user.put()
extra_info = UserTwitterOauth(parent=my_user, key_name="UserTwitterOauth")
extra_info.put()

Вы можете добавить простой метод или свойство к классу User, чтобы упростить извлечение дополнительной информации, и метод класса к UserTwitterOauth, который будет служить фабричным методом, сохраняя соглашение.

Кстати, обратите внимание, что User - это опасное имя для сущности - в API пользователя также есть класс с именем User, и если вы не очень осторожны с импортом, вы можете обратиться к нему, когда вы намерены обратиться к другому.

0 голосов
/ 07 июня 2011

Ссылочное свойство для пользователя с помощью маркера доступа в твиттере, на мой взгляд, проще всего поддерживать.Это правда, что на пользователя могут ссылаться многие токены доступа.

Однако при работе с GAE вы будете часто делать что-то по соглашению.токены, ссылающиеся на одного и того же пользователя:

Вы можете получить доступ к ссылочным токенам в виде запроса через свойство User.usertwitteroauth_set.Если вам нужно более описательное имя, укажите параметр collection_name при настройке ReferenceProperty.Скажем, например, что вы хотите удалить все ссылающиеся токены доступа, прежде чем добавлять новый, вы можете собрать эту логику следующим образом:

class User(db.Model):
    def set_access_token(self, access_token):
        db.delete(self.twitter_access_tokens) # Think this should work, otherwise iterate over the query.
        new_access_token.user = self
        new_access_token.put()


class UserTwitterOauth(db.Model):
    user = db.ReferenceProperty(User, collection_name = 'twitter_access_tokens')
...