5 января 2010 в 22:40

Pyrant+PyModels — легчайшая замена Django ORM*

Тихо и незаметно вышла ноль-первая версия библиотеки Pyrant, т.е. Pythonic Tyrant.

Pyrant — это полноценная питонья обвязка для Tokyo Tyrant, сетевого интерфейса для Tokyo Cabinet.

Tokyo Cabinet — это современное, легкое, гибкое и суперское хранилище данных (DBM). Оно поддерживает несколько типов БД, включая как простейшее key/value, так и «табличное», а вернее — документо-ориентированное. Последнее ставит Tokyo в один ряд с такими славными продуктами как CouchDB, MongoDB и др., при этом TC/TT значительно проще и легче, а поэтому быстрее. Кроме того, он поддерживает достаточно сложные запросы по данным (см. список операторов) с различением строчных и числовых значений. И еще для Tokyo Cabinet можно писать расширения на Lua.
А еще, а еще — PyModels! Да-да, Pyrant+PyModels уже сейчас сильно напоминает Django ORM. Только легче в сотни раз :)

Пример работы с Pyrant:

$ ttserver test.tct &
$ python
>>> import pyrant
>>> t = pyrant.Tyrant()
>>> t.query
[]
>>> t['guido'] = {'name': 'Guido', 'age': 53}
>>> t['larry'] = {'name': 'Larry', 'age': 55}
>>> t.query.filter(age__gt=53)
[(u'guido', {u'name': u'Guido', u'age': u'53'})]
>>> t.query.filter(name__matches='^.+ry$')
[(u'larry', {u'name': u'Larry', u'age': u'55'})]
>>> guys = t.query.filter(name='Guido') | t.query.filter(name='Larry')
>>> guys.columns('age')
[{u'age': u'53'}, {u'age': u'55'}]

Здесь мы видим, что числа сохраняются как строки (хотя по ним можно делать выборки и сортировку как по числам). Вышеупомянутая библиотека PyModels позволяет автоматически обрабатывать входящие и исходящие значения нужным образом, а также оборачивает результаты выборки в экземпляры моделей, так что в итоге всё максимально удобно:

>>> storage = Storage()    # использует Pyrant
>>> class Person(Model):
...     name = Property()
...     age = Number()
...     def __unicode__(self):
...         return self.name
>>> q = Person.query(storage).filter(name__contains='G')
>>> guido = q[0]
>>> guido
<Person Guido>
>>> guido.age
53

_________
Примечания:
* Pyrant+PyModels — действительно замена Django ORM, но серебряной пули нет. Давайте жить дружно. Базы данных всех типов, объединяйтесь. =)

UPD: Models были переименованы в PyModels, топик откорректирован.
Andy @neithere
карма
45,0
рейтинг 0,0
Похожие публикации
Самое читаемое Разработка

Комментарии (41)

  • +1
    фак. только спать хотел пойти, а закончится ковырянием в tyrant до утра.
    и как я такое успел прошляпить…
  • –1
    конкретно, чем лучше django orm?
    • –2
      symfony/propel vs symfony/doctrine
      • +5
        Неверная аналогия. Django ORM — это интерфейс к реляционным БД, Pyrant+Models — к нереляционной БД. Там совсем другой принцип работы, некоторые вещи не работают принципиально, некоторые работают сильно быстрее. Разница не в синтаксисе, как между propel и doctrine, а глубже.
      • +2
        в дополнение к посту выше. соответственно на задачах например простейшего документооборота, где часто приходится делать свою «псевдообъектную обёртку» над реляционными БД можно получить выигрыш как от уменьшения количества кода так и по скорости.
    • 0
      легковесностью же
  • 0
    3 питон поддерживается?
    • 0
      Если потребуется — будет :)
      • +1
        Я вообще придерживаюсь позиции, что любые новые проекты желательно делать и в версии для python3. Я понимаю, что в продакшн пока сложно это засунуть, но вечно на 2 ветке нельзя оставаться. Если есть возможность — лучше уж сразу писасть совместимый код.

        Вот пару часов как-раз начал PyMongo портировать на Py3.1. Повеселюсь чувствую…

        Во, кстати заметил ссылку на bitbucket в комментариях (предлагаю добавить в пост), если будет время может и им займусь.
        • 0
          Было бы славно! Ссылку добавил. Кстати, насчет PyMongo: есть ли смысл делать в Models бэкенд для неё? По-моему, было бы славно обеспечить в приложениях более-менее drop-in совместимость между разными бессхемными базами. Не знаю, как быть с каучем, но у MongoDB довольно стандартный API, клеевой код должен получиться тонким… или нет?
          • 0
            К сожалению не обладаю достаточным опытом работы с «бессхемными базами», осваиваю вот, но в принципе не вижу пока явных проблем с добавлением бекенда.

            Единственное, не знаю вот как там будет с регулярными выражениями в запросах типа
            «t.query.filter(name__matches='^.+ry$')»
        • 0
          А каким образом хендлить две версии? Есть идеи, как бы содержать всë в чистоте и порядке? :)
          • 0
            2 ветки в основном репозитории + свой репозиторий у мейнтейнера. КО.
          • 0
            Думаю, лучше всего ориентироваться на обсуждение переноса Django на Python 3. То есть, избегать расслоения кода на ветки py2/py3.
  • +1
    Спасибо тебе огромное за models!
    А интересно ли тебе заняться интеграцией Pyrant в обратную сторону, с Django Admin Interface?
    Увы, база данных без GUI / WebUI для меня не достаточно удобна в использовании…
    • +2
      Я сначала хотел Pyrant прикрутить именно к Джанге, потому что пока всё делаю в ней, но после осмотра бэкенда для CouchDB мне кажется, что лучше немного подождать. Django ORM очень сильно привязан к SQL. Очевидно среди ведущих разработчиков пробудился интерес к schema-less/non-sql и какое-то движение началось, но я с трудом представляю себе, какой объем работы нужен для отвязывания моделей и механизмов запросов от подмножества БД, сколько эта работа может занять и кому попадет под хвост достаточно жгучая вожжа, чтобы таки эту самую работу сделать, а не просто поковыряться палочкой.

      Кроме того, недавно надо было для джанговой админки сделать динамически генерируемые формы (EAV), так столько ржавых граблей обнаружилось под листвою, что мне уже эта админка кажется не таким уж и преимуществом. Во всяком случае, в нынешнем виде.

      По-моему, проще взять какие-нибудь Pylons и воткнуть туда Pyrant с Models. Может быть, и новую админку написать-прицепить. В сущности, не так уж и много работы нужно, чтобы получить generic barebones админку (list/CRUD), основанную на какой-нибудь фреймворконезависимой форм-библиотеке. Джанговы формы хороши, но они же не единственные такие в мире. Можно и что-то ближе к Fulton сваять.

      Что касается Models — просто в какой-то момент стало интересно, зачем в Джанге всё так сложно и нельзя ли проще. Как ни странно, оказалось, что можно %)
      Оно пока сырое, но работает… Кстати, я еще не закоммитил новую версию, где Pyrant вынесен в backends. Так что можно админку делать для более широкой ниши.
      • 0
        увы, в админке джанго накоплено огромное количество фич.
        как и в любом большом проекте, понемногу накапливаются неудобства.
        но эти фичи есть, они есть сразу, они работают.
        пока не лезешь сильно глубоко, соотношение фич к неудобствам у Django Admin великолепное.
        то же самое касается Django Forms, Django urlconf, Django middleware, django.contrib.auth, django 3rd party plugins, и прочих вещей…
        а если самому всё постоянно делать идеально, то и жизни не хватит!

        и вообще, мне лично интересно именно быстрое прототипирование на Django, мне нравятся быстрые и легко масштабируемые базы данных. поэтому у меня недюжинный интерес к этой теме.

        а что касается поддержки Django,
        то, во-первых, есть django-couchdb, из которого можно черпать вдохновение,
        во-вторых, товарищи любители NoSQL для Django замышляют более удобные классы для поддержки нереляционных баз данных (в django-dev последние сообщения на эту тему тут и здесь),
        а в-третьих, Alex Gaynor провёл большую работу, связанную с освобождением кода Django от хардкоженного SQL для m2m: Commit 11710 и необходимую для поддержки множества разных баз данных в Django (Commit 11952).
        • 0
          > пока не лезешь сильно глубоко, соотношение фич к неудобствам у Django Admin великолепное. [...] а если самому всё постоянно делать идеально, то и жизни не хватит!

          Дык в том и проблема, что Django снимает множество вопросов, за что приходится платить позже. Как понадобится что-то, о чем авторы Django не думали, монолитность джанги ка-а-ак шабаркнет граблеручкой по лбу… Удивляться не приходится, ведь такова ниша проекта.

          Писать с нуля всё целиком — затея не гиблая (ибо та же Django — результат такой затеи), но очень рискованная, тяжелая и требующая редкого сочетания личных качеств у авторов. Поэтому я и рассматриваю вариант с Pylons, где тоже всё более-менее готово, а связность компонентов не такая жесткая и можно экспериментировать свободнее.

          Внешние приложения — половина могущества фреймворка. Терять их было бы печально. Но тут надо учесть, что ряд наиболее популярных из них включает в себя целые куски сырого SQL и поэтому в любом случае должен быть портирован на конкретный бэкенд. Может быть, со временем к тому и придем в рамках сохранения смысла слова «reusable». А пока особенной разницы между django-mptt-pyrant и models-mptt не видится. Кроме того, что последний можно было бы использовать не только в Джанге, но где угодно еще, включая консольные приложения. То же и с django-voting и подобными.

          Некоторые существующие приложения при смене бэкенда вообще теряют смысл. Например, django-tagging в Tyrant реализуется обычным текстовым полем и лукапом __contains (хранилище само умеет различать tokens в строках и всяко эффективно искать по ним).

          Ну и, да, часть сложных приложений жестко завязана на API различных компонентов Django и отвинтить всё это не представляется возможным: django-filter, django-photologue и т.д.; переписывать тяжело, и чтобы пользоваться ими, нужно написать джанговый бэкенд на базе Pyrant.

          > во-первых, есть django-couchdb, из которого можно черпать вдохновение

          Вдохновение ли. Мне кажется, там выбран довольно странный подход. Преимущества и особенности кауча игнорируются, база притягивается за уши к чужеродной среде. Карьерный экскаватор с реактивным двигателем.

          > во-вторых, товарищи любители NoSQL для Django замышляют более удобные классы для поддержки нереляционных баз данных (в django-dev последние сообщения на эту тему тут и здесь),

          Во-от, именно эту штуку я и жду :)
          По-моему, у Вальдемара сейчас всё сломано. Я удовольствием занялся бы написанием бэкенда, когда будет более-менее стабильная нереляционная веточка, серьёзно метящая в транк. Впрочем, сейчас почитаю ссылки, мейби выяснится что-то новое и счастливое.
  • 0
    спасибо за новость. как то прошло мимо. надо будет присмотрется. т.к. админка вс1 равно в проекте не используется попробую потестить :)
    • +1
      neithere скромно умолчал, что это все его рук дело. Так что благодарить его стоит вовсе не за новость)
      • 0
        Спасибо) Models действительно пока дело только моих копытец, а Pyrant — плод коллективного труда. Будет славно, если со временем сформируется сообщество вокруг обоих проектов.
  • 0
    > так и «табличное», а вернее — документо-ориентированное

    Скажите, пожалуйста, где об этом можно почитать подробнее?
    • +1
      О чем именно?

      Под «document-oriented database» я понимаю хранилище записей произвольной структуры. CouchDB и MongoDB эту структуру хранят в JSON, а Tokyo Cabinet — в строке, которую расширение TDB дополнительно дробит на пары ключ/значение. Таким образом, кауч и монго вообще не накладывают ограничений на структуру документа, токио ограничивает вложенность (можно сериализовать значения, но тогда отрубится часть поисковых фич), а реляционные БД ограничивают еще и количество и типы свойств документа. Реляционные — это таблицы, а док.-ориент. — вменяемая реализация EAV, где entity — документ, а attribute/value — свойство документа.

      Можно об этом почитать Катца (автора CouchDB) и комменты: damienkatz.net/2006/05/document_orient.html
      А можно некоторые мои измышления (чуть устаревшие и скорее об RDF): neithere.net/dev/notes/databases/
      Ну и какой-то обзорчик, собственно, покоится в википедии: en.wikipedia.org/wiki/Document-oriented_database
      • 0
        Что такое документо-ориентированные БД я знаю. Не знал что Tokyo Cabinet умеет работать в «табличном» режиме. Стало интересно, что под этим подразумевается.
        • 0
          Грубо говоря, table_database = {'primary_key': '\x00'.join('name', 'john', 'age', '123')}
          Т.е. табличный режим — просто надстройка над key/value. Главное щасье — в механизме поиска, который из коробки правильно работает с сериализованными значениями, не путает названия со значениями.
  • 0
    А я так и не понял — кто автор? Martin Conte Mac Donell, или вы?
    Я бы привязал это дело к twisted наверное. Схемы URL от джанго + pyrant + twisted + jinja + чего-нибудь для форм, и вышел бы славный, очень производительный, фреймворк.
    Почему twisted, а не пилонсы или торнадо? Потому что twisted это не только HTTP, а взаимодействовать надо зачастую с разными протоколами, да и нравится мне возможность гибко лавировать между использованием генераторного стиля и макаронно-колбечного. В случае с колбеками можно породить независимый процесс обработки какой-нибудь.
    • 0
      > А я так и не понял — кто автор? Martin Conte Mac Donell, или вы?

      См. habrahabr.ru/blogs/python/80062/#comment_2354085
      Pyrant написан МакДонеллом на базе кода Ипполито и Флоренцано, а затем значительно улучшен мною и lasizoillo.
      Models написал я.

      > Я бы привязал это дело к twisted наверное.

      Мне пока не довелось работать с Twisted, поэтому чрезвычайно туманно представляю себе результат. Может, распишете подробнее с примерами? Не исключено, что в итоге был бы смысл так и сделать. Необходимость гибкого и легковесного (не)веб-фреймворка очевидна. Под «не-веб» имею в виду «слепой» сервер rest/json с возможностью втыкать нужную логику на питоне. Это очень похоже на CouchDB, но там мне не нравится навязывание «вывернутой» модели разработки. Попробуй замени бэкенд, когда всё твое приложение — middleware.
      • 0
        Знаете, я наверное перепишу pyrant и сделаю tx-pyrant. Просто если переписаться на твистед, то с обычными скриптами там делать уже нечего — надо обязательно уже работать только в рамках твистед. Будет ветка: )

        А вот по логике втыкаемой, тут я не очень понимаю — это получается REST прослойка между сервером tyrrant и конечным клиентом? Ну на твистед это легко достаточно сделать. Просто надо всегда помнить, что мы работает в одном потоке, и тяжелые обработки надо скидывать в другие потоки.
        • 0
          Если возьметесь, добавьте здесь ссылку, плиз. Интересно. :)
          • 0
            Начало здесь:
            github.com/Deepwalker/tx-tokyo

            Сейчас сделал базу — без pythonic/dict like. Потому что мне не совсем прозрачно, как через yield делать выборку из словаря: ) Поэтому я думаю, что dict like я оторву. Не такая уж это великая сложность вместо []= написать .set().
            • 0
              Вы, похоже, форкнули старую версию, которая лежит у Мартина. По-моему, лучше брать то, что на битбакете.

              Про выборку ничего не понял, подожду кода с примером :)
              Вообще, имхо, есть смысл стараться работать с каким-то одним из слоев (протокол, dict-like, query) и стараться сохранять API этого слоя. Это возможно в нашем случае или нет?
              • 0
                Просто удобно использовать в Twisted декоратор defer.inlineCallbacks, а он предполагает использование yield. Ну и мне сомнительно, чтобы можно было написать так — yield db['kuku']='data', да и колбек тут тоже повесить некуда: ) То есть неблокирующие операции имеют свою цену в некотором снижении удобства, но от этого пока никуда не деться.
                Потому и api просто так не перельется — из-за вот таких вот заморочек.
                Я хочу собрать фреймворк полностью, поэтому буду думать, как сделать лучше и удобнее.
              • +1
                Кстати у меня получилось все — ваш код models не пришлось даже трогать — habrahabr.ru/blogs/python/80339/
                github.com/Deepwalker/deepwalker_sandbox
                • 0
                  Замечательно! Кстати, в следующей версии Models всё, что связано с Pyrant, будет вынесено в models.backends.tyrant. Если все стандартные тесты Pyrant ваша ветка пройдет, с бэкендом проблем тоже не будет. Только надо подумать, как обеспечить взаимозаменяемость pyrant и tx-pyrant. Можно сделать доп. бэкенд на основе имеющегося (просто подменять класс Tyrant). Можно поступить как с факультативными сишными реализациями обычно, т.е. try/except с приоритетом tx (?). Ну и вообще интересно, есть ли смысл в существовании параллельных версий в перспективе.
  • –1
    Лучше бы допилили привязку Django ORM к MongoDB, которая bitbucket.org/kpot/django-mongodb/
    • +1
      Тоже вариант. Но необходимость патчить джангу очень-очень сильно смущает. Я все проекты держу на транке. Нет более бездарной траты времени, чем поиски бага, вызванного недокументированным конфликтом библиотек и патчей. Именно поэтому мне кажется, что есть смысл подождать, пока тот же Вальдемар допилит и вольет в транк свой мегапатч. См. habrahabr.ru/blogs/python/80062/#comment_2354038
  • 0
    UPD: Models были переименованы в PyModels, поскольку имя библиотеки (т.е. базовые модели и тд) конфликтовало с именем локального модуля (где сидят ваши модели). Соответственно, поменялись ссылки. Статью обновил.
    • 0
      … и, наконец, в Docu :)

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.