Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Peewee – лёгкая, эластичная и дюже стремительная ORM на Python

Anna | 15.06.2014 | нет комментариев

Предлагаю каждому джангистам/алхимистам немножко отвечься и почитать вольную интерпретацию вводного туториала и Отчасти документации по 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 – список либо кортеж двухэлементных кортежей, где 1-й элемент – значение для базы, 2-й – отображаемое значение (подобно джанге);
  • 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()

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


Источник: programmingmaster.ru

Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB