GAE NDB запутался в моделях и дублирующихся атрибутах

Я пытаюсь изучить NDB Google App Engine и не понимаю структуру моделей.

Моя ситуация похожа на платформу CMS с типами сообщений (как в WordPress), поэтому у меня есть «Блоги» и «Страницы». Для всех этих типов сообщений требуется одинаковый набор атрибутов: родительский элемент, имя, ярлык, шаблон, содержимое, статус и дата.

До сих пор я понимаю, что мне нужно создать модель для них следующим образом:

class Post(ndb.Expando):
    parent = ndb.StringProperty()
    name = ndb.StringProperty()
    slug = ndb.StringProperty()
    template = ndb.StringProperty()
    content = ndb.StringProperty(indexed=False)
    status = ndb.StringProperty()
    date = ndb.DateTimeProperty(auto_now_add=True)

(Я использую Expando, потому что буду добавлять «неизвестные» атрибуты в свое приложение)

Но с такой структурой все мои сообщения (в каждом типе сообщений) будут относиться к одному и тому же «типу», поэтому запросы будут занимать больше времени (если я не ошибаюсь).

  • Как я могу создать много моделей (видов) с одинаковыми атрибутами?
  • Нужно ли копировать и вставлять приведенную выше модель под разными именами классов?
  • Можно ли динамически создавать новые модели (аналогично «Пользовательским типам записей» в WordPress)? Будет ли это работать, если я использую ndb.Key('Blog', blogid) вместо объявления модели?
  • Создаю ли я модель под названием class PostType(ndb.Model), которая хранит «Типы сообщений» и дает им предков сообщений? (Если я не ошибаюсь, это вызовет проблемы, потому что обновление сообщения «заблокирует» все дерево предков на секунду или около того)

Моя основная цель — эффективность. Спасибо!

Обновления:

Как написали Дэн и Мгилсон, добавление подклассов основного класса Post Model — хороший способ решить эту проблему:

class Post(ndb.Expando):
    parent = ndb.StringProperty()
    name = ndb.StringProperty()
    slug = ndb.StringProperty()
    template = ndb.StringProperty()
    content = ndb.StringProperty(indexed=False)
    status = ndb.StringProperty()
    date = ndb.DateTimeProperty(auto_now_add=True)

class Blog(Post):
    pass

Однако это требует статического написания моделей. Есть ли способ сделать это динамически (без предварительного объявления их как моделей)?

Обновлять:

Следуя приведенному ниже совету, я решил сохранить все свои объекты под одним и тем же kind. Позже я мог бы решить изменить это на подклассы (отдельные kinds для каждого «типа сообщения»), если мои запросы станут беспорядочными. Спасибо всем за ваши отличные советы!


person ThePloki    schedule 17.06.2016    source источник
comment
Подхватывать только этот бит будет в пределах одного вида, поэтому запросы будут занимать больше времени (если не ошибаюсь). Вы ошибаетесь. Количество сущностей в хранилище данных не влияет на время, необходимое для запроса.   -  person Greg    schedule 17.06.2016
comment
Потенциальная проблема с подклассами заключается в том, что это разные типы сущностей, поэтому вы не можете просто запросить все сообщения и блоги в одном запросе. Возможно, вам это не нужно, в этом случае все в порядке. Если да, то вы смотрите на что-то вроде полимоделей. Вы можете создавать модели на лету, однако для этого вам нужно будет начать использовать API гораздо более низкого уровня и, возможно, метаклассы. На данный момент ваши вопросы говорят о том, что вы еще не готовы к этому. Если все модели имеют одни и те же свойства, почему бы просто не включить свойство Post Type и упростить задачу.   -  person Tim Hoffman    schedule 18.06.2016


Ответы (2)


Как я могу создать много моделей с одинаковыми атрибутами?

Вы можете подкласс:

class SpecialPost(Post):
    """Special post type that is a different kind than Post."""

Хотя часто достаточно просто использовать тот же тип и просто добавить дополнительное поле, представляющее тип сообщения, который вы можете фильтровать в запросах.

Можно ли динамически создавать новые модели (аналогично «Пользовательским типам записей» в WordPress)? Будет ли это работать, если я использую ndb.Key('Blog', blogid) вместо объявления модели?

Я не уверен на 100%, что понимаю, о чем вы здесь спрашиваете. Вы можете динамически создавать модели так же, как вы можете динамически создавать классы в python (используя type), но вы, вероятно, не хотите этого делать. Получение этих динамически созданных моделей (и отслеживание их имен), вероятно, приведет к серьезным головным болям.

person mgilson    schedule 17.06.2016
comment
Спасибо за ответ. Причина, по которой я не хочу использовать один и тот же тип для всех типов сообщений, заключается в том, что запрос всех сообщений во всех типах сообщений звучит как плохая практика. Я бы предпочел запросить определенный тип сообщения (где тип сообщения = вид). Запрос всех сущностей по сравнению с запросом определенного типа сильно влияет на время отклика? Я не должен беспокоиться об этом? - person ThePloki; 17.06.2016
comment
@ThePloki - хранилище данных создано с учетом супермасштабируемости. Пока у вас есть индекс запрашиваемого свойства, не должно быть большой разницы во времени загрузки. Определенно существуют другие причины, по которым вы можете захотеть хранить их отдельно (например, разные типы сообщений могут иметь разные свойства). - person mgilson; 17.06.2016

По сути, простой пример подкласса, о котором уже упоминал @mgilson.

class Post(ndb.Expando):
    parent = ndb.StringProperty()
    name = ndb.StringProperty()
    slug = ndb.StringProperty()
    template = ndb.StringProperty()
    content = ndb.StringProperty(indexed=False)
    status = ndb.StringProperty()
    date = ndb.DateTimeProperty(auto_now_add=True)

class Blog(Post):
    someint = ndb.IntegerProperty()

blog = Blog(status='new', someint=2)
key = blog.put()
print key.kind()

Что касается динамического создания моделей, из документа Constructor модели:

Приложение обычно не вызывает Model(), но, скорее всего, вызовет конструктор класса, наследуемого от Model. Это создает новый экземпляр этой модели, также известный как объект.

Даже если это возможно (я не копался слишком глубоко в ndb/models.py, чтобы с уверенностью сказать, что это не так), это не кажется ясным. Лично я бы держался подальше от этого и вместо этого переосмыслил необходимость таких динамически создаваемых моделей.

person Dan Cornilescu    schedule 17.06.2016
comment
Большое спасибо, это очень помогает! - person ThePloki; 18.06.2016