Что такое ORM? ORM дословно Object Relational Mapping - объектно-реляционное связывание - комплекс программ, позволяющих работать с базами данных, как если бы они были объектами языка программирования, в данном случае Python.

Или иначе - ORM это набор классов, добавляющих еще один уровень абстракции к таблицам, хранящимся в базе данных. Эта абстракция позволяет работать с объектами БД как с объектами используемого языка программирования, не отвлекаясь на их преобразование в язык SQL. ORM целесообразно использовать в больших проектах, использующих БД, однако для повышения скорости выполнения запросов некоторые программисты предпочитают самостоятельно формировать нужные SQL-запросы. Причина в том, что в случае сложных запросов ORM не всегда генерирует оптимальный SQL-запрос к БД, что в случае большой выборки весьма существенно, особенно если выборка идет по нескольким таблицам. Несмотря на существующие недостатки, ORM широко распространены и существуют во многих языках программирования: Java, C#, PHP, Python, C++ и др.

Использовать ORM в ваших проектах или нет - решать Вам, однако я настоятельно рекомендую ознакомиться с этой технологией, так как она широко используется во многих сферах, в том числе в Java Enterprise.

На сегодняшний момент существует несколько ORM для Python, среди них:

  1. SQLAlchemy
  2. Django-ORM
  3. PonyOrm
  4. PeeWee
  5. SQLObject

Наиболее популярной является 1 и 2, однако 3 и 4 являются хорошей альтернативой.

Системы ORM 1 и 2 - это два больших монстра, хотя и позволяют выполнить многое, но как говорит гугл, в этом случае производительность по сравнению с обычным SQL-запросом падает до 3 раз.

Системы 3 и 4 позиционируются как легковесные, не обладают полным функционалом 1 и 2, но его достаточно для выполнения большинства сложных запросов. Стоит отметить, что их производительность по сравнению с 1 или 2 выше.

Для простоты рассмотрим особенности работы с PeeWee.

Для установки пакета с командной строке наберите pip install peewee.

Определение модели

Классы модели, поля и экземпляры сущности все отображаются на концепцию базы данных.

Термин Соответствие
Класс модели таблица в БД
Экземпляр поля столбец в таблице
Экземпляр сущности строка в таблице

При создании проекта с peewee, можно начать с определения модели.

from peewee import *
# Создаем подключение к БД
db = SqliteDatabase('people.db')

class Person(Model):
    name=CharField()
    birthday=DateField()
    is_relative=BooleanField()
    
    # Здесь мы указываем соединение с БД
    class Meta:
        database=db

В этом примере мы создаем подключение к базе данных SQLite (файл people.db) и определяем класс модели Person. В этом же классе в подклассе Meta расположена database - переменная соединения с БД.

Внимание! мы назвали нашу модель Person вместо People. Вы должны придерживаться этого правила, даже если таблица будет содержать множество людей, мы всегда назовем класс существительным в единственном числе.

В PeeWee определено много типов столбцов:

Field Type Sqlite Postgresql MySQL
CharField varchar varchar varchar
FixedCharField char char char
TextField text text longtext
DateTimeField datetime timestamp datetime
IntegerField integer integer integer
BooleanField integer boolean bool
FloatField real real real
DoubleField real double precision double precision
BigIntegerField integer bigint bigint
SmallIntegerField integer smallint smallint
DecimalField decimal numeric numeric
PrimaryKeyField integer serial integer
ForeignKeyField integer integer integer
DateField date date date
TimeField time time time
TimestampField integer integer integer
BlobField blob bytea blob
UUIDField text uuid varchar(40)
BareField untyped not supported not supported

Чтобы открыть соединение с БД нужно написать

db.connect()

и хотя в мануале пишут, что это не обязательно, тем не менее это хорошая практика, так как позволяет обнаружить ошибки при соединении.

Определение связей происходит при помощи внешнего ключа

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

    class Meta:
        database = db # this model uses the "people.db" database

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

создание таблиц в БД происходит следующим образом:

db.create_tables([Person, Pet])

сохранение экземпляра класса в БД происходит по команде:

save()

Пример:

grandma = Person.create(name='Grandma', birthday=date(1935, 3, 1), is_relative=True)

grandma.save()

Подробная документация находится здесь

Прежде чем бросаться и писать ORM обертку для таблиц сущностей, сначала надо спроектировать логическую структуру БД или ХД. Установить все зависимости и способы взаимодействия между сущностями.

ORM SQLAlchemy

Работа с этой ORM начинается с импорта элементов из пакета sqlalchemy.

Для подключения к БД мы создаем объект Engine, который создает связку пула подключения и диалекта конкретной БД.

Далее нужно создать базовый класс для объявления сущностей наших данных

Потом мы описываем связываемые таблицы через наследование от класса Base.

from sqlalchemy import create_engine

engine = create_engine('sqlite:///:memory:', echo=True)

from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()

from sqlalchemy import Column, Integer, String

class User(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    name = Column(String)
    fullname = Column(String)
    password = Column(String)
    
    def __repr__(self):
        return "<User(name='%s', fullname='%s', password='%s')>" % (
            self.name, self.fullname, self.password)

В этом примере мы определили связку сущности User и таблицы users.

Для создания экземпляра сущности просто создайте объект класса User.

u=User(name='Isac', fullname='Newton', password='123')

Указывать параметры при вызове конструктора не обязательно, присвоить значения полям экземпляра сущности можно и после.


u=User()
u.name='Isac'
u.fullname='Newton'
u.password='123'

Для того, чтобы связаться с базой данных и начать с ней диалог, создадим класс сессия.

from sqlalchemy.orm import sessionmaker
Session = sessionmaker(bind=engine)

# и создадим экземпляр этого объекта
session=Session()

теперь мы можем сохранять наши экземпляры сущностей в базу.

ed_user = User(name='ed', fullname='Ed Jones', password='edspassword')
session.add(ed_user)
session.add(u)
session.commit()

Обратите внимание, что после commit() поле id примет автоматически инициализированного значения. (id - первичный ключ, автоинкрементный)