Статьи

Python 101: введение в пони ORM

Проект Pony ORM — это еще один пакет реляционных объектов для Python. Они позволяют запрашивать базу данных с использованием генераторов. У них также есть онлайн-редактор диаграмм ER, который должен помочь вам создать модель. Это также один из немногих пакетов Python, которые я видел со схемой мульти-лицензирования, где вы можете разрабатывать с использованием лицензии GNU или приобретать лицензию для работы без открытого исходного кода. Смотрите их сайт для получения дополнительной информации.

В этой статье мы потратим некоторое время на изучение основ этого пакета.


Начиная

Поскольку этот проект не входит в состав Python, вам необходимо скачать и установить его. Если у вас есть пункт, то вы можете просто сделать это:

pip install pony

В противном случае вам придется скачать исходный код и установить его через скрипт setup.py .


Создание базы данных

Мы начнем с создания базы данных для хранения некоторой музыки. Нам понадобятся две таблицы: Artist и Album. Давайте начнем!

import datetime
import pony.orm as pny
 
database = pny.Database("sqlite",
                        "music.sqlite",
                        create_db=True)
 
########################################################################
class Artist(database.Entity):
    """
    Pony ORM model of the Artist table
    """
    name = pny.Required(unicode)
    albums = pny.Set("Album")
 
########################################################################
class Album(database.Entity):
    """
    Pony ORM model of album table
    """
    artist = pny.Required(Artist)
    title = pny.Required(unicode)
    release_date = pny.Required(datetime.date)
    publisher = pny.Required(unicode)
    media_type = pny.Required(unicode)
 
# turn on debug mode
pny.sql_debug(True)
 
# map the models to the database 
# and create the tables, if they don't exist
database.generate_mapping(create_tables=True)

Pony ORM создаст для нас наш первичный ключ автоматически, если мы его не укажем. Чтобы создать внешний ключ, все, что вам нужно сделать, это передать класс модели в другую таблицу, как мы делали в классе Album. Каждое обязательное поле принимает тип Python. Большинство наших полей имеют юникод, одно из которых является объектом времени данных. Затем мы включаем режим отладки, который выводит SQL, который Pony генерирует при создании таблиц в последнем операторе. Обратите внимание, что если вы запустите этот код несколько раз, вы не создадите таблицу заново. Пони проверит, существуют ли таблицы перед их созданием.

Если вы запустите приведенный выше код, вы должны увидеть что-то похожее на это:

GET CONNECTION FROM THE LOCAL POOL
PRAGMA foreign_keys = false
BEGIN IMMEDIATE TRANSACTION
CREATE TABLE "Artist" (
  "id" INTEGER PRIMARY KEY AUTOINCREMENT,
  "name" TEXT NOT NULL
)
 
CREATE TABLE "Album" (
  "id" INTEGER PRIMARY KEY AUTOINCREMENT,
  "artist" INTEGER NOT NULL REFERENCES "Artist" ("id"),
  "title" TEXT NOT NULL,
  "release_date" DATE NOT NULL,
  "publisher" TEXT NOT NULL,
  "media_type" TEXT NOT NULL
)
 
CREATE INDEX "idx_album__artist" ON "Album" ("artist")
 
SELECT "Album"."id", "Album"."artist", "Album"."title", "Album"."release_date", "Album"."publisher", "Album"."media_type"
FROM "Album" "Album"
WHERE 0 = 1
 
SELECT "Artist"."id", "Artist"."name"
FROM "Artist" "Artist"
WHERE 0 = 1
 
COMMIT
PRAGMA foreign_keys = true
CLOSE CONNECTION

Разве это не было аккуратно? Теперь мы готовы научиться добавлять данные в нашу базу данных.


Как вставить / добавить данные в ваши таблицы

Пони делает добавление данных в ваши таблицы довольно безболезненным. Давайте посмотрим, насколько это просто:

import datetime
import pony.orm as pny
 
from models import Album, Artist
 
#----------------------------------------------------------------------
@pny.db_session
def add_data():
    """"""
 
    new_artist = Artist(name=u"Newsboys")
    bands = [u"MXPX", u"Kutless", u"Thousand Foot Krutch"]
    for band in bands:
        artist = Artist(name=band)
 
    album = Album(artist=new_artist,
                  title=u"Read All About It",
                  release_date=datetime.date(1988,12,01),
                  publisher=u"Refuge",
                  media_type=u"CD")
 
    albums = [{"artist": new_artist,
               "title": "Hell is for Wimps",
               "release_date": datetime.date(1990,07,31),
               "publisher": "Sparrow",
               "media_type": "CD"
               },
              {"artist": new_artist,
               "title": "Love Liberty Disco", 
               "release_date": datetime.date(1999,11,16),
               "publisher": "Sparrow",
               "media_type": "CD"
              },
              {"artist": new_artist,
               "title": "Thrive",
               "release_date": datetime.date(2002,03,26),
               "publisher": "Sparrow",
               "media_type": "CD"}
              ]
 
    for album in albums:
        a = Album(**album)
 
if __name__ == "__main__":
    add_data()
 
    # use db_session as a context manager
    with pny.db_session:
        a = Artist(name="Skillet")

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


Использование базовых запросов для изменения записей с помощью Pony ORM

В этом разделе мы узнаем, как сделать несколько базовых запросов и изменить несколько записей в нашей базе данных.

]
import pony.orm as pny
 
from models import Artist, Album
 
with pny.db_session:
    band = Artist.get(name="Newsboys")
    print band.name
 
    for record in band.albums:
        print record.title
 
    # update a record
    band_name = Artist.get(name="Kutless")
    band_name.name = "Beach Boys"

Здесь мы используем db_session в качестве менеджера контекста. Мы делаем запрос, чтобы получить объект Artist из базы данных и напечатать его имя. Затем мы перебираем альбомы исполнителя, которые также содержатся в возвращаемом объекте. Наконец, мы меняем одно из имен художника.

Давайте попробуем сделать запрос к базе данных с помощью генератора:

result = pny.select(i.name for i in Artist)
result.show()

Если вы запустите этот код, вы должны увидеть что-то вроде следующего:

i.name
———————
Newsboys
MXPX
Beach Boys
Тысяча футов

В документации есть несколько других примеров, которые стоит проверить. Обратите внимание, что Pony также поддерживает использование самого SQL через методы select_by_sql и get_by_sql .


Как удалить записи в Pony ORM

Удаление записей с Пони также довольно легко. Давайте удалим одну из полос из базы данных:

import pony.orm as pny
 
from models import Artist
 
with pny.db_session:
    band = Artist.get(name="MXPX")
    band.delete()

Еще раз мы используем db_session для доступа к базе данных и фиксации наших изменений. Мы используем метод delete объекта band для удаления записи. Вам нужно будет копать, чтобы узнать, поддерживает ли Pony каскадное удаление, и если вы удалите Artist, он также удалит все альбомы, которые к нему подключены. Согласно документам , если поле Обязательное, то каскад включен.


Завершение

Теперь вы знаете основы использования пакета Pony ORM. Лично я считаю, что документация требует небольшой работы, так как вам нужно много копать, чтобы найти ту функциональность, которая, по моему мнению, должна была быть в уроках. В целом, документация все же намного лучше, чем в большинстве проектов. Попробуйте и посмотрите, что вы думаете!


Дополнительные ресурсы