Google App Engine Python Datastore - PullRequest
2 голосов
/ 07 января 2011

По сути, я пытаюсь создать структуру данных, в которой есть имя пользователя, идентификатор и дата соединения.Тогда я хочу "подструктуру", где он имеет "текст" пользователей и дату, когда он был изменен.и у пользователя будет несколько экземпляров этого текста.

class User(db.Model):
    ID = db.IntegerProperty()         
    name = db.StringProperty()
    datejoined = db.DateTimeProperty(auto_now_add=True)

class Content(db.Model): 
    text = db.StringProperty()
    datemod= db.DateTimeProperty(auto_now_add = True)   

Правильно ли настроен код?

Ответы [ 3 ]

4 голосов
/ 07 января 2011

Одна из проблем, с которой вы столкнетесь, заключается в том, что создание уникального User.ID будет нетривиальным. Проблема состоит в том, что две записи в базу данных могут происходить на разных шардах, оба проверяют примерно в одно и то же время существующие записи, которые соответствуют ограничению уникальности и не находят ни одного, затем обе создают идентичные записи (относительно уникального свойства), а затем иметь недопустимое состояние базы данных. Для решения этой проблемы appengine предоставляет средство, гарантирующее, что определенные сущности хранилища данных всегда размещаются на одном физическом компьютере.

Для этого вы используете ключи сущностей, чтобы сообщить Google, как организовать сущности. Предположим, вы хотите, чтобы имя пользователя было уникальным. Измените User, чтобы оно выглядело так:

class User(db.Model):
    datejoined = db.DateTimeProperty(auto_now_add=True)

Да, это действительно так. Там нет имени пользователя, так как он будет использоваться в ключе, поэтому он не должен появляться отдельно. Если хотите, вы можете сделать это ...

class User(db.Model):
    datejoined = db.DateTimeProperty(auto_now_add=True)

    @property
    def name(self):
        return self.key().name()

Чтобы создать экземпляр User, теперь вам нужно сделать что-то немного другое, вам нужно указать key_name в методе init.

someuser = User(key_name='john_doe')
...
someuser.save()

Ну, на самом деле вы хотите убедиться, что пользователи не перезаписывают друг друга, поэтому вам нужно заключить создание пользователя в транзакцию. Сначала определите функцию, которая выполняет необходимую проверку:

def create_user(username):
    checkeduser = User.get_by_key_name(username)
    if checkeduser is not None:
        raise db.Rollback, 'User already exists!'
    newuser = User(key_name=username)
    # more code
    newuser.put()

Затем, вызовите его таким образом

db.run_in_transaction(create_user, 'john_doe')

Чтобы найти пользователя, вы просто делаете это:

someuser = User.get_by_key_name('john_doe')

Далее вам нужно каким-то образом связать контент с его пользователем, и наоборот. Одно из решений состоит в том, чтобы поместить контент в ту же группу сущностей, что и пользователь, объявив пользователя родителем контента. Для этого вам вообще не нужно менять контент, но вы создаете его немного по-другому (так же, как вы это делали с пользователем):

somecontent = Content(parent=User.get_by_key_name('john_doe'))

Итак, с учетом элемента контента вы можете найти пользователя, проверив его ключ:

someuser = User.get(somecontent.key().parent())

В обратном порядке, поиск всего контента для конкретного пользователя является лишь немного хитрее.

allcontent = Content.gql('where ancestor is :user', user=someuser).fetch(10)
1 голос
/ 07 января 2011

Альтернативное решение, которое вы можете увидеть, это использование referenceproperty.

    class User(db.Model):
        name = db.StringProperty()
        datejoined = db.DateTimeProperty(auto_now_add=True)

    class Content(db.Model):
        user = db.ReferenceProperty(User,collection_name='matched_content')
        text = db.StringProperty()
        datemod= db.DateTimeProperty(auto_now_add = True)

    content = db.get(content_key)
    user_name = content.user.name

    #looking up all of the content for a particular user
    user_content = content.user.matched_content

    #create new content for a user
    new_content = Content(reference=content.user)
1 голос
/ 07 января 2011

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

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