Тихо и незаметно вышла ноль-первая версия библиотеки
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, топик откорректирован.
комментарии (39)
и как я такое успел прошляпить…
Вот пару часов как-раз начал PyMongo портировать на Py3.1. Повеселюсь чувствую…
Во, кстати заметил ссылку на bitbucket в комментариях (предлагаю добавить в пост), если будет время может и им займусь.
Единственное, не знаю вот как там будет с регулярными выражениями в запросах типа
«t.query.filter(name__matches='^.+ry$')»
А интересно ли тебе заняться интеграцией Pyrant в обратную сторону, с Django Admin Interface?
Увы, база данных без GUI / WebUI для меня не достаточно удобна в использовании…
Кроме того, недавно надо было для джанговой админки сделать динамически генерируемые формы (EAV), так столько ржавых граблей обнаружилось под листвою, что мне уже эта админка кажется не таким уж и преимуществом. Во всяком случае, в нынешнем виде.
По-моему, проще взять какие-нибудь Pylons и воткнуть туда Pyrant с Models. Может быть, и новую админку написать-прицепить. В сущности, не так уж и много работы нужно, чтобы получить generic barebones админку (list/CRUD), основанную на какой-нибудь фреймворконезависимой форм-библиотеке. Джанговы формы хороши, но они же не единственные такие в мире. Можно и что-то ближе к Fulton сваять.
Что касается Models — просто в какой-то момент стало интересно, зачем в Джанге всё так сложно и нельзя ли проще. Как ни странно, оказалось, что можно %)
Оно пока сырое, но работает… Кстати, я еще не закоммитил новую версию, где Pyrant вынесен в backends. Так что можно админку делать для более широкой ниши.
как и в любом большом проекте, понемногу накапливаются неудобства.
но эти фичи есть, они есть сразу, они работают.
пока не лезешь сильно глубоко, соотношение фич к неудобствам у 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).
Дык в том и проблема, что 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 последние сообщения на эту тему тут и здесь),
Во-от, именно эту штуку я и жду :)
По-моему, у Вальдемара сейчас всё сломано. Я удовольствием занялся бы написанием бэкенда, когда будет более-менее стабильная нереляционная веточка, серьёзно метящая в транк. Впрочем, сейчас почитаю ссылки, мейби выяснится что-то новое и счастливое.
Скажите, пожалуйста, где об этом можно почитать подробнее?
Под «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
table_database = {'primary_key': '\x00'.join('name', 'john', 'age', '123')}Т.е. табличный режим — просто надстройка над key/value. Главное щасье — в механизме поиска, который из коробки правильно работает с сериализованными значениями, не путает названия со значениями.
Я бы привязал это дело к twisted наверное. Схемы URL от джанго + pyrant + twisted + jinja + чего-нибудь для форм, и вышел бы славный, очень производительный, фреймворк.
Почему twisted, а не пилонсы или торнадо? Потому что twisted это не только HTTP, а взаимодействовать надо зачастую с разными протоколами, да и нравится мне возможность гибко лавировать между использованием генераторного стиля и макаронно-колбечного. В случае с колбеками можно породить независимый процесс обработки какой-нибудь.
См. habrahabr.ru/blogs/python/80062/#comment_2354085
Pyrant написан МакДонеллом на базе кода Ипполито и Флоренцано, а затем значительно улучшен мною и lasizoillo.
Models написал я.
> Я бы привязал это дело к twisted наверное.
Мне пока не довелось работать с Twisted, поэтому чрезвычайно туманно представляю себе результат. Может, распишете подробнее с примерами? Не исключено, что в итоге был бы смысл так и сделать. Необходимость гибкого и легковесного (не)веб-фреймворка очевидна. Под «не-веб» имею в виду «слепой» сервер rest/json с возможностью втыкать нужную логику на питоне. Это очень похоже на CouchDB, но там мне не нравится навязывание «вывернутой» модели разработки. Попробуй замени бэкенд, когда всё твое приложение — middleware.
А вот по логике втыкаемой, тут я не очень понимаю — это получается REST прослойка между сервером tyrrant и конечным клиентом? Ну на твистед это легко достаточно сделать. Просто надо всегда помнить, что мы работает в одном потоке, и тяжелые обработки надо скидывать в другие потоки.
github.com/Deepwalker/tx-tokyo
Сейчас сделал базу — без pythonic/dict like. Потому что мне не совсем прозрачно, как через yield делать выборку из словаря: ) Поэтому я думаю, что dict like я оторву. Не такая уж это великая сложность вместо []= написать .set().
Про выборку ничего не понял, подожду кода с примером :)
Вообще, имхо, есть смысл стараться работать с каким-то одним из слоев (протокол, dict-like, query) и стараться сохранять API этого слоя. Это возможно в нашем случае или нет?
Потому и api просто так не перельется — из-за вот таких вот заморочек.
Я хочу собрать фреймворк полностью, поэтому буду думать, как сделать лучше и удобнее.
github.com/Deepwalker/deepwalker_sandbox