|
Cetus Group
Информационные системы и программное обеспечение
Меню
Поддержка
E-mail:
cetus@ukr.net
|
Object Relation Mapper (ORM) в Python
Размещено 13.11.2007 : Дополнено 16.11.2007
А.Г. © Часть 1 - "Проба ORM Storm"При разработке программ на ОО-языках программирования для работы с БД, в качестве которых обычно применяют реляционные СУБД, возникают проблемы несоответствия структуры и интерфейса классов программы структуре и отношениям таблиц РСУБД. Одним из решений этой проблемы являются ORM-системы, которые предоставляют объектно-ориентированный интерфейс к таблицам реляционных БД, поддерживают структуру таблиц и отношения между таблицами. Для работы с ORM Storm понадобится работающий сервер баз данных MySQL с базой данных "test", модуль MySQLdb и дистрибутив Storm. Пример выполнен в последней версией Storm - 0.11. 1. Устанавливаем Storm. Для установки достаточно поместить каталог Storm-"версия" в /usr/local/lib и добавить в "/ваш/каталог/пайтон/site-packages" ссылку на Storm-"версия"/storm. 2. Создаем базу данных. В настоящее время Storm не позволяет создавать таблицы БД на основе описания моделей, поэтому создадим таблицы в БД 'test' выполнением двух запросов (в примере использован переработанный код сравнительного тестирования Storm, SQLAlchemy, and Geniusql):
DROP table if exists Animal;
CREATE TABLE Animal (
ID INT4 NOT NULL auto_increment primary key,
MotherID INT4,
ZooID INT4,
PrefFoodID INT4,
AltFoodID INT4,
LastEsc TIMESTAMP,
Name VARCHAR(100),
Age INT(2),
Lifespan FLOAT4,
PrevZoos TEXT,
Legs INT4 DEFAULT 4,
Species VARCHAR(100)
);
DROP table if exists Zoo;
CREATE TABLE Zoo (
ID INT4 auto_increment primary key,
Name VARCHAR(255),
Admission DECIMAL(6, 2),
Founded DATE,
LastEsc TIMESTAMP,
Opens TIME
);
3. Создаем описание двух моделей для тестирования:
import storm
from storm.locals import *
class Zoo(Storm):
__storm_table__ = 'Zoo'
ID = Int(primary=True)
Name = Unicode()
Founded = Date()
Opens = Time()
LastEsc = DateTime()
Admission = Float()
def __init__(self, **kwargs):
for k, v in kwargs.iteritems():
setattr(self, k, v)
class Animal(Storm):
__storm_table__ = 'Animal'
ID = Int(primary=True)
MotherID = Int()
ZooID = Int()
zoo = Reference("ZooID", "Zoo.ID")
Name = Unicode()
Species = Unicode()
Legs = Int(default=4)
LastEsc = DateTime()
Lifespan = Float()
mother = Reference(MotherID, ID)
PrefFoodID = Int()
AltFoodID = Int()
def __init__(self, **kwargs):
for k, v in kwargs.iteritems():
setattr(self, k, v)
4. Выполняем простой пример, в котором:
#!/usr/bin/python
#-*- coding: utf-8 -*-
from model1 import *
import datetime
# Create/open database
db = create_database('mysql://mysql:@localhost/test')
conn = db.connect()
store = Store(db)
# Create Zoo objects
wap = Zoo(Name=u'Wild Animal Park',
Founded=datetime.date(2000, 1, 1),
Opens=datetime.time(8, 15, 59),
LastEsc=datetime.datetime(2004, 7, 29, 5, 6, 7),
Admission=4.95
)
store.add(wap)
sdz = Zoo(Name = u'San Diego Zoo',
Founded = datetime.date(1835, 9, 13),
Opens = datetime.time(9, 0, 0),
Admission = 0
)
store.add(sdz)
print "--1- Zoo.ID, Zoo.Name before flush:"
print wap.ID, "\t", wap.Name
print sdz.ID, "\t", sdz.Name
store.flush()
store.commit()
print
print "--2- Zoo.ID, Zoo.Name after flush:"
for zoo in store.find(Zoo):
print zoo.ID, "\t", zoo.Name.encode("latin1")
store.add(Animal(Species='Леопард', Lifespan=73.5, ZooID=sdz.ID))
store.add(Animal(Species='Тигр', Legs=1, Lifespan=.75, ZooID=sdz.ID))
store.add(Animal(Species='Медведь', ZooID=wap.ID))
store.add(Animal(Species='Лев', ZooID=wap.ID))
store.flush()
store.commit()
print
print "--3- Animal.ID, Animal.Species after flush:"
for animal in store.find(Animal):
print animal.ID, "\t", animal.Species.encode("latin1")
print
print "--4- Zoo.Name, Animal.Species after search:"
for zoo in store.find((Zoo,Animal),"Zoo.ID=Animal.ZooID"):
print zoo[0].Name.encode("latin1"), "\t", zoo[1].Species.encode("latin1")
store.close()
5. Получаем результаты: --1- Zoo.ID, Zoo.Name before flush: None Wild Animal Park None San Diego Zoo --2- Zoo.ID, Zoo.Name after flush: 1 Wild Animal Park 2 San Diego Zoo --3- Animal.ID, Animal.Species after flush: 1 Тигр 2 Медведь 3 Лев 4 Леопард --4- Zoo.Name, Animal.Species after search: San Diego Zoo Тигр Wild Animal Park Медведь Wild Animal Park Лев San Diego Zoo Леопард К сожалению оригинальная сборка Storm изначально не позволила работать с кириллицей, что потребовало косметической правки в инсталляции Storm. Кроме этого, если при создании объекта в имени атрибута базы данных будет допущена ошибка - такой атрибут не только не будет инициализирован (что понятно), но и не будет выдано сообщение об ошибке (что плохо). Тем не менее, несмотря на эти "шероховатости" и раннюю версию, ORM Storm имеет хорошо продуманный интерфейс, интересные возможности формирования сложных запросов при работе с хранилищем, высокую скорость работы. |