Веб-фулстак
0,0
рейтинг
24 декабря 2013 в 13:35

Разработка → Peewee – лёгкая, гибкая и очень быстрая ORM на Python tutorial

image

Предлагаю всем джангистам/алхимистам немного отвечься и почитать вольную интерпретацию вводного туториала и частично документации по Peewee – stand-alone ORM, обязательной к ознакомлению любому питонщику и, в особенности, фласкеру. Пишут о ней мало, а зря. С Peewee очень просто подружиться, особенно если вы уже знакомы с какой-нибудь ORM на ActiveRecord. Что более важно – с ней приятно дружить :) Ну, начнём.


Установка
С pip:
pip install peewee


Из репозитория:
git clone https://github.com/coleifer/peewee.git cd peewee python setup.py install


Тесты:
python setup.py test


Есть обвязка для flask:
pip install flask-peewee



Определение моделей или «попахивает джангой»


Весь нижеследующий код можно повторить один к одному в интерактивном интерпретаторе или отдельном скрипте.

from peewee import *

db = SqliteDatabase('people.db')

class Person(Model):
    name = CharField()
    birthday = DateField()
    is_relative = BooleanField()

    class Meta:
        database = db  # модель будет использовать базу данных 'people.db'


Типов полей много, на все случаи жизни. Peewee берёт на себя преобразование питоновских объектов в значения, подходящие для базы данных, и наоборот.

Инициализирующие аргументы


Каждое поле принимает следующие инициализирующие аргументы:
  • null=False – возможно ли хранение null-значений;
  • index=False – создавать ли индекс для данного столбца в базе;
  • unique=False – создавать ли уникальный индекс для данного столбца в базе. См. также главу о составных индексах;
  • verbose_name=None – строка для человекопонятного представления поля;
  • help_text=None – строка с вспомогательным текстом для поля;
  • db_column=None – строка, явно задающая название столбца в базе для данного поля, используется например при работе с legacy базой данных;
  • default=None – значение по-умолчанию для полей класса при инстанцировании;
  • choices=None – список или кортеж двухэлементных кортежей, где первый элемент – значение для базы, второй – отображаемое значение (аналогично джанге);
  • primary_key=False – использовать ли данное поле, как первичный ключ;
  • sequence=None – последовательность для наполнения поля (удостоверьтесь, что бекэнд поддерживает такую функциональность);


Метаданные


Для каждой таблицы можно прописать единые метаданные в class Meta:

Опция Описание Наследуется?
database база данных для модели да
db_table название таблицы, в которой будут храниться данные нет
indexes список полей для индексирования да
order_by список полей для сортировки по-умолчанию да
primary_key составной первичный ключ, экземпляр класса CompositeKey, пример да
table_alias алиас таблицы для использования в запросах нет


Попробуем задать отношения между моделями через внешний ключ. С peewee это просто:

class Pet(Model):
    owner = ForeignKeyField(Person, related_name='pets')
    name = CharField()
    animal_type = CharField()

    class Meta:
        database = db  # модель будет использовать базу данных 'people.db'


Модели описаны, осталось создать для них соответствующие таблицы в базе данных:

>>> Person.create_table()
>>> Pet.create_table()


Работа с данными


Для примера создадим нескольких человек и заведём им домашних животных:

>>> from datetime import date
>>> uncle_bob = Person(name='Bob', birthday=date(1960, 1, 15), is_relative=True)
>>> uncle_bob.save()  # cохраним Боба в базе данных


Записи можно создавать и напрямую с помощью метода Model.create() без явного save():

>>> grandma = Person.create(name='Grandma', birthday=date(1935, 3, 1), is_relative=True)
>>> herb = Person.create(name='Herb', birthday=date(1950, 5, 5), is_relative=False)


Порадуем бабулю фамилией:

>>> grandma.name = 'Grandma L.'
>>> grandma.save()  # обновим запись grandma


Теперь сгенерируем немного живности. У бабули аллергия на кошек, а вот у Герба есть некоторые проблемы:

>>> bob_kitty = Pet.create(owner=uncle_bob, name='Kitty', animal_type='cat')
>>> herb_fido = Pet.create(owner=herb, name='Fido', animal_type='dog')
>>> herb_mittens = Pet.create(owner=herb, name='Mittens', animal_type='cat')
>>> herb_mittens_jr = Pet.create(owner=herb, name='Mittens Jr', animal_type='cat')


В какой-то момент Варежке надоело жить с Гербом и, воспользовавшись открытым окном, он гордо убежал в закат. Уважая его право на свободу личности, всё же удалим соответствующую запись из базы:

>>> herb_mittens.delete_instance()  # удачи, Варежка
1


Как вы могли заметить, операция удаления возвращает количество удалённых записей, в данном случае – 1.

Дядя Боб решил, что у Герба итак много животных и отжал у него Фидо:

>>> herb_fido.owner = uncle_bob
>>> herb_fido.save()
>>> bob_fido = herb_fido  # переименуем переменную для лучшего соответствия суровой реальности


Выборки


Выборки выполняются прямо с объектом класса и возвращают экземпляры SelectQuery (аналог QuerySet в джанге).

Извлечение одной записи


Для извлечения одной записи используйте метод SelectQuery.get():

>>> grandma = Person.select().where(Person.name == 'Grandma L.').get()


Запрос можно сократить, подставив аргумент напрямую в get():

>>> grandma = Person.get(Person.name == 'Grandma L.')


Извлечение нескольких записей


Пройдемся по всем экземплярам Person циклом:

>>> for person in Person.select():
...     print person.name, person.is_relative
...
Bob True
Grandma L. True
Herb False


Пройдемся по экземплярам Person и по всем связанным с ними записями:

>>> for person in Person.select():
...     print person.name, person.pets.count(), 'pets'
...     for pet in person.pets:
...         print '    ', pet.name, pet.animal_type
...
Bob 2 pets
    Kitty cat
    Fido dog
Grandma L. 0 pets
Herb 1 pets
    Mittens Jr cat


Выловим всех кошек и их хозяев людей (или наоборот?):

>>> for pet in Pet.select().where(Pet.animal_type == 'cat'):
...     print pet.name, pet.owner.name
...
Kitty Bob
Mittens Jr Herb


Не без join'ов:

# выберем всех животных Боба
>>> for pet in Pet.select().join(Person).where(Person.name == 'Bob'):
...     print pet.name
...
Kitty
Fido


Извлечь ту же выборку можно и по-другому – явно передав объект с Бобом в запрос:

>>> for pet in Pet.select().where(Pet.owner == uncle_bob):
...     print pet.name


Упорядочим выборку в алфавитном порядке. Для этого воспользуемся методом SelectQuery.order_by():

>>> for pet in Pet.select().where(Pet.owner == uncle_bob).order_by(Pet.name):
...     print pet.name
...
Fido
Kitty


Упорядочим людей по возрасту:

>>> for person in Person.select().order_by(Person.birthday.desc()):
...     print person.name
...
Bob
Herb
Grandma L.


Давайте попробуем более сложный запрос. Выберем всех людей, родившихся
  • до 1940
  • после 1959


>>> d1940 = date(1940, 1, 1)
>>> d1960 = date(1960, 1, 1)
>>> for person in Person.select().where((Person.birthday < d1940) | (Person.birthday > d1960)):
...     print person.name
...
Bob
Grandma L.


Хинт
Запрос where((Person.birthday < d1940) | (Person.birthday > d1960)) можно написать и как where(Person.birthday < d1940 or Person.birthday > d1960), но лучше этого не делать, т.к. peewee не всегда правильно обрабатывает такую запись.


А теперь торобоан. Выберем тех, кто родился между 1940 и 1960:

>>> for person in Person.select().where((Person.birthday > d1940) & (Person.birthday < d1960)):
...     print person.name
...
Herb


And one last thing. Воспользуемся SQL-функцией и выберем всех людей, чьё имя начинается с «G» в любом регистре:

>>> for person in Person.select().where(fn.Lower(fn.Substr(Person.name, 1, 1)) == 'g'):
...     print person.name
...
Grandma L.


Для выборок также используйте методы:
  • SelectQuery.group_by()
  • SelectQuery.having()
  • SelectQuery.limit() и SelectQuery.offset()


Если вам понравился данный краткий туториал, обязательно посетите официальную документацию — там много интересного, включая рецепты с решениями распространённых задач и набор плагинов, расширяющих базовую функциональность.

Бонус


Автора в его блоге спросили о быстродействии ORM, на что тот ответил:

On my machine peewee has been faster than Django and SQA at most tasks, and about the same when iterating and returning Model instances.

На моём компе peewee обошла Django и SQLAlchemy на большинстве задач, и показала сравнимые результаты на итерациях и выборке инстансов.


После чего опубликовал результаты бенчмарка на гитхабе. Тестились обычные модели и связанные через ForeignKey в различных сценариях. Весьма любопытно.

Кому интересно, исходники:


Хорошая альтернатива Алхимии, как считаете?
Николай @rzhannoy
карма
23,2
рейтинг 0,0
Веб-фулстак
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

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

  • +3
    Маленькая, клевая, очень удобная.
    Отмечу пару моментов:
    — весь орм в одном файле, почти 3к строк (на дворе 2013 г.)
    — расширяемость под вопросом, т.к. QueryCompiler вызывает методы поля db_value и python_value для каждого объекта — если подсунуть ему итератор, то разберет и вызовет эти методы для каждого элемента. Помню, что пытался использовать постгресовские массивы да нифига не вышло: отдаешь ему [0, 1, 2], а он тебе [conv.db_value(i) for i in params] — список просто не доходит целиком до обработки в филде, следовательно надо переписывать компилятор, а это уже сама ормка. Хотя может я не разобрался как следует.
  • 0
    Исходники, да ещё и в одном модуле (ну кто так делает) меня смутили. Хотя не видел ещё ORM с нормальным кодом под капотом, везде макароны и магия.
  • 0
    В закладки, с нетерпением жду миграций.
    P.S: Боюсь представить, каким количеством магии реализовано это
      .where((Person.birthday > d1940) & (Person.birthday < d1960))
    

    Респект.
    • +3
      Так же как и в SQLAlchemy — перегрузкой операторов
    • 0
      С миграциями пока туго, так что — либо ручками, либо пишем свой модуль и выкладываем его в народ)
      Как вариант — ссылка ниже.
  • 0
    как у него с миграциями?
    • 0
      Currently peewee does not have support for automatic schema migrations

      Руками, как я понимаю.
    • 0
      Есть простой мигратор. Модуль, прямо скажем, так себе, но для простых случаев подойдёт.

      Если хочется что-то вроде south, придётся написать самому.
  • +2
    Хорошая альтернатива Алхимии, как считаете?

    Сейчас использую в pyhon в качестве orm ponyorm. А то я как человек избалованный Spring Data становлюсь грустной пандой от DSL в других python orm
    • 0
      Чем же вам не понравилась алхимия? Самая мощная Python ORM, да DSL у нее очень даже ничего
      • 0
        джанга и алхимия — тормозные, увы
      • 0
        DSL у него отстой. Я так в java два года назад писал. Сейчас пишу совсем по другому. И в этом плане ponyorm существенно лучше чем Алхимия. Я сначала то использовал алхимию, но на уровне SQL, а вот когда я захотел ORM… и я туда посмотрел, то мне захотелось помыть глаза с хлоркой. Такой подход еще в статическом языке как-то оправдан в динамическом нет.
        • 0
          Интересно, я уже давно слежу за PonyOrm, но мне почему-то наоборот казалось что оно настолько похоже на алхимию что мигрировать с одного на другое смысла нет. Единственное в чем я вижу разницу так это в способах создания запросов — генераторы в пони против обычных выражений типа: .filter((Person.birthday > d1940) & (Person.birthday < d1960)). Во всем всем остальном DSL почти 1 в 1 как алхимии, судя по докам.
          • 0
            Интересно, я уже давно слежу за PonyOrm, но мне почему-то наоборот казалось что оно настолько похоже на алхимию что мигрировать с одного на другое смысла нет.

            Вы там DSL точно смотрели? Давайте обратимся к вот этому посту habrahabr.ru/post/188842/

            SQLAlchemy
             u = session.query(AUser).filter(AUser.id==i+1)[0]
            


            Pony ORM
             u = select(u for u in PUser if u.id==i+1)[:1][0]
            


            Кстати можно написать даже лучше
             u = select(u for u in PUser if u.id==i+1).get()
            


            И да как только потребуется написать более менее сложный запрос, портянка из функций будет все длиннее и длиннее и выглядит это не опрятно и читается еще хуже. В ORM java такое тоже было не так давно. Сейчас есть такая прекрасная штука как Spring Data

            Которая позволяет делать так:
            public interface UserRepository extends Repository<User, Long> {
            
              List<User> findByEmailAddressAndLastname(String emailAddress, String lastname);
            }
            


            И так
            public interface UserRepository extends JpaRepository<User, Long> {
            
              @Query("select u from User u where u.emailAddress = ?1")
              User findByEmailAddress(String emailAddress);
            }
            


            Плюс PonyORM быстрее работает.
            • +1
              Ну, спорить не буду, как говорится на вкус и на цвет фломастеры разные. Но в SQLAlchemy цепочки методов сделаны не просто так, а для того что бы можно было программно конструировать разные запросы в разных частях приложения, в отличии от Pony где вы один раз написали генератор и все. Ну и то что все делается напрямую через сессию, которая не скрыта за какими-то декораторами для функций, тоже плюс, так как это питон и явное лучше неявного. Я тоже плевался когда переходил с Джанги, но как оказалось я просто не умел готовить алхимию. Сейчас работаю с Node.js и с грустью скучаю о алхимии.
              • –2
                Но в SQLAlchemy цепочки методов сделаны не просто так, а для того что бы можно было программно конструировать разные запросы в разных частях приложения, в отличии от Pony где вы один раз написали генератор и все.

                Эм. Поясните мне про что речь. Обычно если вы уж написали последовательный вызов функций в тексте, то так он и будет. Как вы его там менять собираетесь мне право интересно.

                Ну и то что все делается напрямую через сессию, которая не скрыта за какими-то декораторами для функций, тоже плюс, так как это питон и явное лучше неявного.

                В ponyorm скрыта сессия? Где?
                • 0
                  Эм. Поясните мне про что речь. Обычно если вы уж написали последовательный вызов функций в тексте, то так он и будет. Как вы его там менять собираетесь мне право интересно.

                  Так я именно про это и говорю — алхимия позволяет не писать последовательный вызов функций в одном месте. В одном месте мы можем сделать JOIN, во втором — второй JOIN, в третьем мы можем опять таки программно сконструировать фильтр, а в четвертом применить сортировку. Это же обычные методы, как мы захотим так их и скомбинируем. Это позволяет разбивать и выделать общие запросы и на этом и основывается вся работа в алхимии — вы создаете классы которые уже имеют все нужные вам реляции (с джоинами или без) которые затем просто фильтруются или на их основе делаются более сложные запросы.

                  В ponyorm скрыта сессия? Где?

                  Вот и я не знаю где, все что я вижу это глобальные функции типа commit и rollback которые на самом деле где-то управляют сессией но саму сессию я не вижу, и это меня смущает.
                  • 0
                    Так я именно про это и говорю — алхимия позволяет не писать последовательный вызов функций в одном месте. В одном месте мы можем сделать JOIN, во втором — второй JOIN, в третьем мы можем опять таки программно сконструировать фильтр, а в четвертом применить сортировку. Это же обычные методы, как мы захотим так их и скомбинируем.

                    Эм. У меня дурацкий вопрос. Что мешает это делать в случае ponyorm? Вызов там ровно точно такой же. Вызвали select написали что надо оно сгенерило.

                    Это позволяет разбивать и выделать общие запросы и на этом и основывается вся работа в алхимии — вы создаете классы которые уже имеют все нужные вам реляции (с джоинами или без) которые затем просто фильтруются или на их основе делаются более сложные запросы.

                    Эм… а кто вам сказал что реляций в ponyorm то нет?

                    Вот и я не знаю где, все что я вижу это глобальные функции типа commit и rollback которые на самом деле где-то управляют сессией но саму сессию я не вижу, и это меня смущает.

                    Официальная дока:

                    Another option for working with the database is using db_session as a context manager instead of a decorator:
                    with db_session:
                        p = Person(name='Kate', age=33)
                        Car(make='Audi', model='R8', person=p)
                        # commit() will be done automatically
                        # transaction cache will be cleared automatically
                        # the database connection will be returned to the pool
                    



                    Я уж не знаю что там вам еще надо.
                    • 0
                      Эм. У меня дурацкий вопрос. Что мешает это делать в случае ponyorm? Вызов там ровно точно такой же. Вызвали select написали что надо оно сгенерило.

                      Ну как мне сделать примерно так?
                      class User(db.Model):
                        id =  db.Column(db.Integer)
                        verified_transactions = db.relationship(
                           Transaction,  primaryjoin=lambda: (Transaction.user_id == User.id) &
                                                             (Transaction.verified == True)
                        )
                        unverified_transactions = db.relationship(
                           Transaction, primaryjoin=lambda: (Transaction.user_id == User.id) &
                                                            (Transaction.verified == False)
                       )
                      
                      class Transaction(db.Model):
                        id =  db.Column(db.Integer)
                        type = db.Column(db.String(32))
                        amount = db.BigInteger() 
                        user =  db.Column(db.Integer, db.ForeignKey(User.id))
                      
                      def filter_txs_by_type(query, type)
                         return query.filter(Transaction.type == type)
                      
                      def filter_txs_by_amount_gt(query, amount):
                         return query.filter(Transaction.amount > amount)
                      
                      all_verified_txs = User.verified_transactions
                      verified_received_txs  = filter_txs_by_type(all_verified_txs, 'RECEIVE')
                      verified_received_txs_gt_1000 = filter_txs_by_amount_gt(verified_received_txs, 1000)   
                      

                      Это конечно немного наигранный пример, но в целом показывает именно то что я хочу описать — программное конструирование запросов
                      Эм… а кто вам сказал что реляций в ponyorm то нет?

                      Они там есть, но не такие мощные как в алхимии

                      Официальная дока:

                      Ну вот вы и привели пример глобальных функций которые сами управляют сессией где-то у себя про что я собственно и говорю
                      • –1
                        Это конечно немного наигранный пример, но в целом показывает именно то что я хочу описать — программное конструирование запросов

                        Первое что я могу сразу сказать, что вот такой код я сразу прошу переписать, без обид. Вы понимаете что делаете? Для того чтобы понять что в итоге выбирается надо залезть в два разных места. Теряется прозрачность за счет этого весьма просто что-то сломать да так что еще и причина будет не очевидна. По этой причине лучше запрос так не дробить.

                        Они там есть, но не такие мощные как в алхимии

                        Ну да бывает что хочется использовать связи с дополнительными фильтрами, но это в ORM вообще довольно редкая фича. И я не могу сказать, что это вызывает серьезные проблемы.

                        Ну вот вы и привели пример глобальных функций которые сами управляют сессией где-то у себя про что я собственно и говорю

                        В смысле управляют сессией? Сессия да глобальная, но вызывать где надо commit это совершенно не мешает. Единственное но когда это может мешать это два подключения к РСУБД, но это надо автора пытать :) Пока к сожалению документация освещает далеко не все.
                        • +2
                          Первое что я могу сразу сказать, что вот такой код я сразу прошу переписать, без обид. Вы понимаете что делаете? Для того чтобы понять что в итоге выбирается надо залезть в два разных места. Теряется прозрачность за счет этого весьма просто что-то сломать да так что еще и причина будет не очевидна. По этой причине лучше запрос так не дробить.

                          Очень-очень странное заявление, если например у нас есть список транзакций и у транзакции есть тип, статус, размер и дата, и нам нужно сделать фильтр по всем этим параметрам не будете же вы писать кучу запросов для каждого варианта. Более того, я могу с уверенностью сказать что любой нормальный проект на SQLAlchemy использует эти возможности и это абсолютно никого не смущает, а наоборот делает код проще и понятнее:
                          github.com/mitsuhiko/bf3-aggregator/blob/master/bf3.py#L586 bitbucket.org/danjac/newsmeme/src/43c4760f94a1308abce92661084b302ca229d7fe/newsmeme/models/posts.py?at=default#cl-45
                          То же самое относится и к реляциям, фильтрованным или нет — это отнюдь не редкая, а наоборот — самая и наиболее часто используемая фича в алхимии, это же в конце концов ORM, а не что-то там еще. Я просто не представляю как можно писать ручками каждый запрос если можно разбить все — вынести реляции, вынести часто используемые фильтры и группировки и зачем просто комбинировать их по мере надобности.
                          • –1
                            Очень-очень странное заявление, если например у нас есть список транзакций и у транзакции есть тип, статус, размер и дата, и нам нужно сделать фильтр по всем этим параметрам не будете же вы писать кучу запросов для каждого варианта.

                            Ничего странного. Просто на выходе все равно будет генерация sql запроса. Я понимаю что DRY и все дела, но вот в этом я бы не советовал.

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

                            Это в алхимии. В других ORM фича довольно редкая, так-как все под связями стараются понимать именно связи между таблицами.

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

                            Запросто при нормальном DSL. В случае DSL как в Alchemy это выглядит как крокодил, по этой причине и начинают делать сокрытие кода и думать как писать лучше, в итоге получаем более сложный код. С дополнительными уровнями сокрытия где и что вызывается.

                            • 0
                              Молодец. Порекламировался? Статья была вообще-то про Peewee, один из самых легковесных ORM.

                              Немного низковато использовать чужой бренд, чужие имена для саморекламы, вы не находите? Неужели так плохо с поклонниками PonyORM, что приходится прибегать к таким методам рекламы? Может, просто, людям и нафиг не нужен этот непривычный синтаксис построения запросов? Может у них другие требования к коду, — не задумывались?

                              Когда мне Гугл выдает по запросу «Python ORM» первой строкой эту мальчишескую подделку ponyorm, и только потом показывает серьезный и глубоко продуманный труд SQLAlchemy, который завоевал действительно широкую аудиторию, я начинаю понимать смысл пословицы «Хороший товар продает себя сам», к которой так и хочется добавить «и не нуждается в услугах SEO-оптимизаторов».
                              • 0
                                Молодец. Порекламировался? Статья была вообще-то про Peewee, один из самых легковесных ORM.

                                Учитывая что к ponyorm я имею отношение только как пользователь, то весьма странное заявление. Я описываю свой опыт работы. И то что я бы хотел видеть. Если вам что-то не нравится это явно ваши проблемы.

                                Немного низковато использовать чужой бренд, чужие имена для саморекламы, вы не находите?

                                По моему немного низковато, начитать наезды. Причем мы тут опытом делимся что как и где. И да многое мне в PonyORM не нравится, о чем я так же писал автору. Если хотите могу и тут рассказать что с моей точки зрения там плохо.

                                Может, просто, людям и нафиг не нужен этот непривычный синтаксис построения запросов? Может у них другие требования к коду, — не задумывались?

                                Тогда такие люди возьмут другие средства. Почему мне не удобно я указывал.

                                Когда мне Гугл выдает по запросу «Python ORM» первой строкой эту мальчишескую подделку ponyorm, и только потом показывает серьезный и глубоко продуманный труд SQLAlchemy

                                И так сначала вы обвиняете меня в том что якобы рекламирую, затем сами поливаете грязью ПО других людей и рекламируете SQLAlchemy. И да я всего лишь воспользовался вашей логикой. Ну я же просто описываю свой опыт. Я посмотрел в так называемый продуманный SQLAlchemy и пока они будут использовать такой адовый синтаксис от которого в java я отказался насколько лет назад и забыл про него как страшный сон, я это использовать не буду.
                                • +1
                                  > сами поливаете грязью ПО других людей

                                  — Процитируете?

                                  > и рекламируете SQLAlchemy

                                  — Не рекламирую, а отмываю от грязи. Поскольку реклама Pony ORM построена на обгаживании SQLAlchemy так же как и Peewee.

                                  Peewee не может быть популярным ввиду своего узкого предназначения. Разработчики ставили цель создать легковесный клон Django ORM, и с этой задачей они справились успешно. Уже потом у проекта появилась своя философия, и они уже далеко ушли от клона Django ORM, но все равно они позиционируются как легковесное решение.

                                  Но в отличии от Peewee, SQLAlchemy очень популярен, и имеет довольно хорошие отзывы весьма авторитетных Питонщиков, вот только один из них (python core developer) asvetlov.blogspot.com/2008/09/sqlalchemy-vs-sqlobject.html

                                  В жизни не поверю, что Pony ORM настолько стал популярным, что оттеснил SQLAlchemy на вторую позицию в выдаче Гугла. Из чего просто напрашивается вывод, что в ход пошли манипуляции SEO.
                                  • 0
                                    — Процитируете?

                                    Цитирую

                                    Когда мне Гугл выдает по запросу «Python ORM» первой строкой эту мальчишескую подделку ponyorm

                                  • 0
                                    Но в отличии от Peewee, SQLAlchemy очень популярен, и имеет довольно хорошие отзывы весьма авторитетных Питонщиков, вот только один из них (python core developer) asvetlov.blogspot.com/2008/09/sqlalchemy-vs-sqlobject.html

                                    Я отрицаю что он популярен?

                                    В жизни не поверю, что Pony ORM настолько стал популярным, что оттеснил SQLAlchemy на вторую позицию в выдаче Гугла. Из чего просто напрашивается вывод, что в ход пошли манипуляции SEO.

                                    Есть такое понятие как релевантность. Достаточно посмотреть что написано в описании и понять почему SQLAlchemy на втором месте. Потому что вы вводите Python ORM причем в случае PonyORM сразу в тексте написано:
                                    Pony is a cool and new Python ORM that lets you query a database using Python generators.

                                    А у SQLAlchemy:
                                    SQLAlchemy is the Python SQL toolkit and Object Relational Mapper that gives
                                    SQLAlchemy is most famous for its object-relational mapper (ORM)


                                    Если ведем в яндексе то на первом месте получим вообще на wiki питона про ORM. Ну и да объясните зачем это авторам PonyORM такое SEO?
                                • 0
                                  > Причем мы тут опытом делимся что как и где.

                                  — Мы тут обсуждаем Peewee. У Вас есть опыт использования Peewee? Тогда расскажите о нем. А иначе Вы не опытом делитесь, а просто присасываетесь к чужому труду (автора статьи, разработчиков Peewee), для продвижения собственных интересов и элементарной рекламы.

                                  Разрабатывали Вы Pony ORM, проплачены Вы ими, или просто добровольный рекламатор, — это сути дела не меняет.
                                  • 0
                                    — Мы тут обсуждаем Peewee. У Вас есть опыт использования Peewee? Тогда расскажите о нем. А иначе Вы не опытом делитесь, а просто присасываетесь к чужому труду (автора статьи, разработчиков Peewee), для продвижения собственных интересов и элементарной рекламы.

                                    ЕЩЕ РАЗ ДЛЯ ТЕХ КТО В ТАНКЕ! Я не имею никакого отношения к разработке PonyORM или его продвижению. Я ПРОСТО ИСПОЛЬЗУЮ ЕГО В СВОИХ СКРИПТАХ! И ОПИСЫВАЮ СВОЙ ОПЫТ! А указывать что и как мне писать будете на своем ресурсе. Этот публичный ресурс и не вам указывать мне что и где мне писать.

                                    Разрабатывали Вы Pony ORM, проплачены Вы ими, или просто добровольный рекламатор, — это сути дела не меняет.

                                    Еще как меняет. Во первых я ничего не рекламирую, а делюсь опытом. И я прежде чем взять PonyORM в использование посмотрел все популярные ORM под Python. И я привожу четкие примеры почему я считаю его лучше. И вот вам как «защитнику» Peeweee абсолютно не делают чести методы его защиты. Фактически вместо того чтобы сказать вот это там лучше, а это там хуже и поэтому тут лучше использовать Peewee вы пришли и заочно без каких либо разбирательств обвинили меня в очернении других ORM и рекламе PonyORM.
                                • 0
                                  А вот и истина, которая отражает реальное положение дел: http://www.google.com/trends/explore#q=Pony+ORM,sqlalchemy

                                  И чем пояснить, что Pony ORM занимает первую позицию по запросу https://www.google.com.ua/search?q=Python+ORM кроме как SEO-шными проделками?
                                  • 0
                                    РЕЛЕВАНТНОСТЬЮ! В случае PonyORM указано Python ORM на центральной странице. И да никто не ищет PonyORM по этому запросу. По одной простой причине, он не является настолько популярным и настолько на слуху как sqlalchemy вполне очевидно, что sqlalchemy ищут по его ключевому слову. И да по вашей логике Peewee накручивает в яндексе. Так-как он там на третьей строчке а sqlalchemy на первой странице вообще нет.

                                    Прежде чем делать такие громкие заявления, разберитесь как работает поиск. Вы еще меня давайте обвините, что мой сайт openembedded.ru находится на первой странице поиска по фразе openembedded потому что я накручиваю SEO.
                                    • 0
                                      > РЕЛЕВАНТНОСТЬЮ!

                                      — когда-то это называлось просто поисковой оптимизацией текста и семантическим ядром. А может и накруткой PR, — не знаю, мне это не интересно. Я не разбирался какие именно методы оптимизации имели место. Но я знаю, что хороший товар продает себя сам.

                                      > что мой сайт openembedded.ru находится на первой странице поиска по фразе openembedded потому что я накручиваю SEO.

                                      — а что, слово openembedded так часто ищут в поисковиках? Не льстите себе…
                                      • 0
                                        не знаю, мне это не интересно. Я не разбирался какие именно методы оптимизации имели место. Но я знаю, что хороший товар продает себя сам.

                                        Тогда будьте добры расскажите что плохо в PonyORM. Кроме обвинений вида это мальчишеская поделка и они накручивают Google я никакого конструктива не увидел.

                                        — а что, слово openembedded так часто ищут в поисковиках? Не льстите себе…

                                        Я тоже могу задать вопрос «А что Python ORM так часто ищут в поисковиках?». И воспользуюсь тем же инструментом что пользовались вы www.google.com/trends/explore#q=Python+ORM,sqlalchemy
                                        Как видим фразу Python ORM в google ищут существенно реже чем SQLAlchemy. В итоге имеем тот же результат что и про openembedded. Ну а себе я льстить не собираюсь.
  • +3
    Все же имечко у этой ORM…
  • 0
    А есть аналог джангового unique_together? и как насчет составных ключей для индексов?
    • 0
      • 0
        Нет. Видимо я не разбираюсь в терминологии. Просто индекс по нескольким полям. Наверное это то, что нужно:
        create_index(model_class, fields[, unique=False])

        Правда это делается не в определении модели.
        • 0
          Не знаю, насколько правильно понял вопрос.
          Можно проставлять обычные индексы и с unique constraint на одно или несколько полей.
          Составные ключи по индексам прописываются в class Meta, как в ссылке выше.
          Насчет unique_together, попробуйте:
          class Meta:
                  indexes = (
                      (('field1', 'field2'), True),
                  )
          

          Второй элемент кортежа это значение для атрибута unique.
          Не уверен именно ли это together или для каждого поля по-отдельности. Вместе было бы логичнее, но нужно пробовать.
  • 0
    Чего только не придумают, что бы не пользовать SQL. Я понимаю, хочется, что бы было проще. Но в результате, код, по моему, ужасен (имеется ввиду не примеры типа hello world а реальные). Так и хожу вокруг да около: вроде как все используют (ORM), а как гляну на очередной «легкий и гибкий» — понимаю, это не мое, не созрел видимо
    • +1
      ORM – это уровень абстракции, со всеми вытекающими, в виде очень ускоренной разработки, отсутствия необходимости переключаться между языками в проекте, отсутствия необходимости помнить об особенностях каждого sql-движка и т.п. Не без компромиссов, как и у любой абстракции.

      На типовых веб-проектах вся мощь sql нужна крайне редко. На большинстве сайтов оверхед орм никогда не станет узким местом, зато времени и денег на разработку сэкономит изрядно. Говорить о том, что скуль лучше, только потому что не осилили орм (и наоборот) некорректно, всему свой инструмент.
  • 0
    Простите за глупый вопрос: возможно ли сделать так:

    Добавим например боба и добавим ему в качестве домашнего животного другого боба(со своими животными).

    Если я сделаю так:
    class Person(Model):
    name = CharField()

    class Person2(Model):
    owner = ForeignKeyField(Person, related_name='person2')
    name = CharField()

    то мне придёться создать over 9000 таких Person[] (если их действительно сможет оказаться столько)
    Хотелось бы иметь некую иерархию, но такую в которой мне не известны заранее кто у кого являеться домашним животным и при этом некоторые из них могут иметь теже свойства что и самый первый Person.

    тоесть получаеться что-то вроде:

    class Person(Model):
    owner = ForeignKeyField(Person, related_name='person')
    name = CharField()

    но так не работает :(

  • 0
    А у меня ещё один глупый вопрос:
    возможно ли при изменении модели изменить её и в «базе» не удаляя саму базу?
    Просто сейчас я ещё разрабатываю будущею структуру базы, но если мне вдруг захочется изменить что-то когда у меня будет ОЧЕНЬ много записей — как мне поступить?
    • 0
      То что вам хочется, называется «миграции». Конкретно в Peewee они есть, но не сильно мощные.

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