ORM Object Relationnal Mapping
Что такое ORM? ORM дословно Object Relational Mapping - объектно-реляционное связывание - комплекс программ, позволяющих работать с базами данных, как если бы они были объектами языка программирования, в данном случае Python.
Или иначе - ORM это набор классов, добавляющих еще один уровень абстракции к таблицам, хранящимся в базе данных. Эта абстракция позволяет работать с объектами БД как с объектами используемого языка программирования, не отвлекаясь на их преобразование в язык SQL. ORM целесообразно использовать в больших проектах, использующих БД, однако для повышения скорости выполнения запросов некоторые программисты предпочитают самостоятельно формировать нужные SQL-запросы. Причина в том, что в случае сложных запросов ORM не всегда генерирует оптимальный SQL-запрос к БД, что в случае большой выборки весьма существенно, особенно если выборка идет по нескольким таблицам. Несмотря на существующие недостатки, ORM широко распространены и существуют во многих языках программирования: Java, C#, PHP, Python, C++ и др.
Использовать ORM в ваших проектах или нет - решать Вам, однако я настоятельно рекомендую ознакомиться с этой технологией, так как она широко используется во многих сферах, в том числе в Java Enterprise.
На сегодняшний момент существует несколько ORM для Python, среди них:
Наиболее популярной является 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 - первичный ключ, автоинкрементный)