SlideShare uma empresa Scribd logo
1 de 39
Baixar para ler offline
SQLAlchemy
доступ к реляционным данным
        в стиле Python


       Юревич Юрий, http://pyobject.ru

     Семинар Учебного центра Люксофт,
             16 сентября 2008
«SQLAlchemy — это
Python SQL тулкит и ORM,
 которые предоставляют
      разработчику
всю мощь и гибкость SQL»
                http://sqlalchemy.org


                                        2
Active Record (Django ORM, Storm)




                                3
Data Mapper (SQLAlchemy)




                           4
Архитектура SQLAlchemy




                         5
Про что будет




                6
Про что (почти) не будет




                           7
Управление схемой данных




                           8
Схема == метаданные




                      9
Создание таблиц: SQL
CREATE TABLE users (
     id INTEGER NOT NULL,
     name VARCHAR(255),
     PRIMARY KEY (id)
  );
CREATE TABLE creds (
     id INTEGER NOT NULL,
     user_id INTEGER,
     login VARCHAR(20),
     passwd VARCHAR(40),
     PRIMARY KEY (id),
     FOREIGN KEY(user_id)
      REFERENCES users (id)
  );



                                10
Создание таблиц: SQLAlchemy
meta = MetaData()
users = Table('users', meta,
    Column('id', Integer, primary_key=True),
    Column('name', Unicode(255)),
  )
creds = Table('creds', meta,
    Column('id', Integer, primary_key=True),
    Column('user_id', Integer, ForeignKey('users.id')),
    Column('login', String(20)),
    Column('passwd', String(40)),
  )




                                                          11
MetaData: что умеет
    Создавать/удалять:
●



        Всё сразу:
    –
            meta.create_all() / meta.drop_all()
        По отдельности:
    –
            users.create() / users.drop()
    Рефлексия:
●



        Потаблично:
    –
          users = Table('users', meta, autoload=True)
        Всё сразу:
    –
          meta.reflect()
    Интроспекция:
●


        meta.tables
    –
                                                        12
MetaData: пример из жизни

# ... описание схемы

def get_indexes():
    return [
        Index('ix_users_id', users.c.id, unique=True),
        Index('ix_creds_id', creds.c.id, unique=True),
        Index('ix_creds_user_id', creds.c.user_id),
    ]

def load():
    # ... загрузка данных
    pass

def postload():
    for ix in get_indexes():
        ix.create()
                                                         13
Язык SQL-выражений




                     14
Для любителей трехбуквенных
            сокращений
    DML (Data Managament Language):
●


        insert/update/delete
    –

    DQL (Data Query Language):
●


        select
    –




                                      15
Insert
    Данные указываются при создании
●

     ins = users.insert(values={'name': u'Jack'})
     ins.execute()

    Данные указываются при выполнении
●

     ins = users.insert()
     ins.execute(name=u'Jack')

    Несколько записей сразу
●

     ins = users.insert()
     ins.execute([{'name': u'Jack'}, {'name': u'Ed'}])

    Явно указывая соединение
●

     engine = create_engine('sqlite:///')
     ins = insert(users)
     engine.connect().execute(ins, {'name': u'Jack'})

                                                         16
Delete
    Условие — SQLAlchemy SQL expression
●

      del_ = users.delete(users.c.name==u'Jack')
      del_.execute()

    Условие — строка с SQL
●

      del_ = users.delete('users.name=:user')
      del_.params({'user': u'Jack'}).execute()




                                                   17
Select
SELECT *
FROM users


q = users.select()


SELECT users.id, users.name
FROM users


                              18
Select
SELECT id
FROM users
WHERE name='Jack'

q = users.select([users.c.id],
             users.c.name==u'Jack')

SELECT users.id
FROM users
WHERE users.name=:name

                                      19
Select
SELECT *
FROM users
JOIN creds ON
creds.user_id=users.id

q = users.join(creds).select()

SELECT users.id, users.name,
       creds.id, creds.user_id,
       creds.login, creds.passwd
JOIN creds ON
users.id=creds.user_id             20
Почему SA SQL Expr?
    Потому что Python круче SQL
●




                                  21
Почему SA SQL Expr?
    Потому что Python круче SQL
●


    Генерация SQL на лету:
●


        q = select([users, creds.c.login],
    –
                   from_obj=users.join(creds),
                   whereclause=users.c.name==u'Jack')
        q = users.select()
    –
        q = q.where(users.c.name==u'Jack')
        q = q.column(creds.c.login)
        q.append_from(join(users, creds))
        SELECT users.id, users.name, creds.login
    –
        FROM users
        JOIN creds ON creds.user_id = users.id
        WHERE users.name = 'Jack'

                                                        22
Object Relational Mapper (ORM)




                                 23
Data Mapper, снова




                     24
Рабочий пример:
 схема данных




                  25
Рабочий пример:
                    таблицы в SQL
CREATE TABLE users (              CREATE TABLE messages (
           id INTEGER NOT NULL,              id INTEGER NOT NULL,
           name VARCHAR(255),                subject VARCHAR(255),
           PRIMARY KEY (id)                  body TEXT,
   );                                        author_id INTEGER,
                                             PRIMARY KEY (id),
CREATE TABLE creds (                         FOREIGN KEY(author_id)
           id INTEGER NOT NULL,              REFERENCES users (id)
           user_id INTEGER,          );
           login VARCHAR(20),
           passwd VARCHAR(20),   CREATE TABLE message_recipients (
           PRIMARY KEY (id),                message_id INTEGER NOT NULL,
           FOREIGN KEY(user_id)             recipient_id INTEGER NOT NULL,
           REFERENCES users (id)            PRIMARY KEY (
                                                message_id, recipient_id),
);                                          FOREIGN KEY(message_id)
                                            REFERENCES messages (id),
                                            FOREIGN KEY(recipient_id)
                                            REFERENCES users (id)
                                    );


                                                                         26
Рабочий пример:
                   Данные
users = {
    u'Jack': ['jack', 'jack-rabbit'],
    u'Edvard': ['ed'],
    u'Mary': ['mary'],
}

messages = (
    {   'author': u'Jack', 'recipients': [u'Edvard', u'Mary'],
        'title': u'The first', 'body': u'Ha-ha, I'm the first!,
    },
    {   'author': u'Edvard', 'recipients': [u'Jack', u'Mary'],
        'title': u'Hey all', 'body': u'Hi, I'm here',
    },
    {
        'author': u'Edvard', 'recipients': [u'Mary'],
        'title': u'The silence', 'body': u'Why are you ignoring me?',
    },
    {
        'author': u'Mary', 'recipients': [u'Jack'],
        'title': u'Hi', 'body': u'Hi, Jack, how are you?',
    },
                                                                      27
)
Рабочий пример:
              таблицы в SA SQL Expr
users = Table('users', meta,
   Column('id', Integer, primary_key=True),
   Column('name', Unicode(255)),
   )

creds = Table('creds', meta,
   Column('id', Integer, primary_key=True),
   Column('user_id', Integer, ForeignKey('users.id')),
   Column('login', String(20)),
   Column('passwd', String(20)),
   )

messages = Table('messages', meta,
   Column('id', Integer, primary_key=True),
   Column('subject', Unicode(255)),
   Column('body', Text),
   Column('author_id', Integer, ForeignKey('users.id')),
   )

message_recipients = Table('message_recipients', meta,
   Column('message_id', Integer, ForeignKey('messages.id'), primary_key=True),
   Column('recipient_id', Integer, ForeignKey('users.id'), primary_key=True),
   )
                                                                           28
Рабочий пример:
                     Mappings
Session = scoped_session(sessionmaker(autoflush=False))

class Base(object):
    def __init__(self, **kwargs):
        for key, value in kwargs.items():
            setattr(self, key, value)

class User(Base):
    pass
class Cred(Base):
    pass
class Message(Base):
    pass

Session.mapper(User, users)                                 # (1)

Session.mapper(Cred, creds, properties={                    # (2)
    'user': relation(User, backref='credentials'),})

Session.mapper(Message, messages, properties={              # (3)
    'recipients': relation(User, backref='inbox',
                           secondary=message_recipients),
                                                                    29
    'author': relation(User, backref='outbox'),})
Рабочий пример:
                  готовность №1
[ 1]>>> import schema as sch
[ 2]>>> import mappings as m

[   3]>>>   engine = create_engine('sqlite:///example.sqlite')
[   4]>>>   sch.meta.bind = engine
[   5]>>>   sch.meta.create_all()
[   6]>>>   m.Session.bind = engine

[ 7]>>> u1 = m.User.query.get(1)
[ 8]>>> u1.id
<<< 1
[ 9]>>> u1.name
<<< u'Jack'
[10]>>> u1.credentials
<<< [<Cred: jack>, <Cred: jack-rabbit>]
[11]>>> u1.outbox
<<< [<Message: from Jack to Edvard, Mary (subj: The first)>]
                                                             30
Рабочий пример:
               выборки
[1]>>> q = m.User.query.filter(User.id>1)
[2]>>> print str(q)
SELECT users.id AS users_id, users.name AS users_name
FROM users
WHERE users.id > ?

[3]>>> q = q.filter(m.User.name!=None)
[4]>>> print str(q)
SELECT users.id AS users_id, users.name AS users_name
FROM users
WHERE users.id > ? AND users.name IS NOT NULL

[5]>>> list(q)
<<< [<User u'Edvard'>, <User u'Mary'>]

[6]>>> q.first()
<<< <User u'Edvard'>
                                                        31
Рабочий пример:
      выборки (продолжение)
[1]>>> rabbit = m.Cred.query.
           filter_by(login='jack-rabbit').one()

[2]>>> rabbit_user = m.User.query.
           filter(User.credentials.contains(rabbit)).
           one()


[3]>>> rabbit_messages = m.Message.query.
           filter(or_(
               Message.author==rabbit_user,
               Message.recipients.contains(rabbit_user)
       ))
[4]>>> list(rabbit_messages)
<<<
[<Message: from Jack to Edvard, Mary (subj: The first)>,
 <Message: from Edvard to Jack, Mary (subj: Hey all)>,
 <Message: from Mary to Jack (subj: Hi)>]              32
Рабочий пример:
          выборки (хардкор)
# Выбрать пользователей, у которых
# в исходящих больше одного сообщения
[1]>>> sess = m.Session()
[2]>>> q = sess.query(m.User, func.count('*')).
               join(m.Message).group_by(m.User).
               having(func.count('*')>1)
[3]>>> list(q)
<<< [(<User u'Edvard'>, 2)]

# Выбрать пользователей, у которых
# во входящих больше одного сообщения
[4]>>> sess = m.Session()
[5]>>> q = sess.query(m.User, func.count('*')).
         join(sch.message_recipients).group_by(m.User).
         having(func.count('*')>1)
[6]>>> list(q)
<<< [(<User u'Jack'>, 2), (<User u'Mary'>, 3)]
                                                      33
Рабочий пример:
                 сессия, unit of work
[   1]>>>   engine = create_engine('sqlite:///example.sqlite', echo=True)
[   2]>>>   sch.meta.bind = engine
[   3]>>>   m.Session.bind = engine
[   4]>>>   sess = m.Session()
[   5]>>>   jack = m.User.query.filter_by(name=u'Jack').one()
2008-09-14 14:19:11,504 INFO sqlalchemy.engine.base.Engine.0x...ca2c SELECT...
[ 6]>>> ed = m.User.query.filter_by(name=u'Edvard').one()
2008-09-14 14:20:22,731 INFO sqlalchemy.engine.base.Engine.0x...ca2c SELECT...
[ 7]>>> jack.name = u'Jack Daniels'
[ 8]>>> sess.dirty
<<< IdentitySet([<User u'Jack Daniels'>])
[ 9]>>> ed.name = u'Edvard Noringthon'
[10]>>> sess.dirty
<<< IdentitySet([<User u'Edvard Noringthon'>, <User u'Jack Daniels'>])
[11]>>> sess.flush()
2008-09-14 14:21:00,535 INFO sqlalchemy.engine.base.Engine.0x...ca2c
UPDATE users SET name=? WHERE users.id = ?
2008-09-14 14:21:00,535 INFO sqlalchemy.engine.base.Engine.0x...ca2c
['Jack Daniels', 1]
2008-09-14 14:21:00,604 INFO sqlalchemy.engine.base.Engine.0x...ca2c
UPDATE users SET name=? WHERE users.id = ?
2008-09-14 14:21:00,604 INFO sqlalchemy.engine.base.Engine.0x...ca2c
['Edvard Noringthon', 2]
                                                                                 34
users = Table(
    'users', meta, ...)

class User:
    pass

mapper(users, User)




 «user» 5 раз, скучно?
                          35
Elixir:
ActiveRecord поверх SQLAlchemy
    Elixir (http://elixir.ematia.de):
●


        Декларативное описание в стиле Django
    –

        События:
    –

             До (update, insert, delete)
         ●


             После (update, insert, delete)
         ●



        Плагины:
    –

             acts_as_versioned (автоматическое хранение истории)
         ●


             acts_as_encrypted (шифрование колонок)
         ●


             associable (аналог Django generic relations)
         ●


             ...
         ●



                                                               36
Еще вкусности SQLAlchemy
    «Хитрые» атрибуты:
●


          Отложенная/непосредственная подгрузка
     –

          SQL-выражение как атрибут
     –

    Партицирование:
●


          Вертикальное (часть таблиц в одной БД, часть в другой)
     –

          Горизонтальное (шардинг, содержимое одной таблицы
     –
                               «раскидано» по таблицам/БД)

    Нетривиальные маппинги:
●


          Несколько маппингов к одному классу
     –

          Маппинг классов к SQL-запросам
     –

    ...
●                                                                  37
Диагноз:
                нужна ли вам SA
    Используете другой           Используете DB
●                            ●

    ORM и счастливы?             API2 и «чистый»
                                 SQL?
        Нет, в SQLAlchemy
    –
        «много буков», нет           Да, SQLAlchemy
                                 –
        смысла                       даст вам это и много
                                     что еще




                                                        38
Вопросы?

 ... не успели задать? - шлите почтой: the.pythy@gmail.com



                                                       39

Mais conteúdo relacionado

Mais procurados

Hacking Your Way To Better Security - php[tek] 2016
Hacking Your Way To Better Security - php[tek] 2016Hacking Your Way To Better Security - php[tek] 2016
Hacking Your Way To Better Security - php[tek] 2016Colin O'Dell
 
Play, Slick, play2-authの間で討死
Play, Slick, play2-authの間で討死Play, Slick, play2-authの間で討死
Play, Slick, play2-authの間で討死Kiwamu Okabe
 
Command-Oriented Architecture
Command-Oriented ArchitectureCommand-Oriented Architecture
Command-Oriented ArchitectureLuiz Messias
 
Automatically Spotting Cross-language Relations
Automatically Spotting Cross-language RelationsAutomatically Spotting Cross-language Relations
Automatically Spotting Cross-language RelationsFederico Tomassetti
 
Javascript & jQuery: A pragmatic introduction
Javascript & jQuery: A pragmatic introductionJavascript & jQuery: A pragmatic introduction
Javascript & jQuery: A pragmatic introductionIban Martinez
 
Implementation Specifications
Implementation SpecificationsImplementation Specifications
Implementation SpecificationsUnmon Mukherjee
 
Drupal csu-open atriumname
Drupal csu-open atriumnameDrupal csu-open atriumname
Drupal csu-open atriumnameEmanuele Quinto
 
DataMapper @ RubyEnRails2009
DataMapper @ RubyEnRails2009DataMapper @ RubyEnRails2009
DataMapper @ RubyEnRails2009Dirkjan Bussink
 
DOSUG Intro to JQuery JavaScript Framework
DOSUG Intro to JQuery JavaScript FrameworkDOSUG Intro to JQuery JavaScript Framework
DOSUG Intro to JQuery JavaScript FrameworkMatthew McCullough
 
MoSQL: More than SQL, but Less than ORM @ PyCon APAC 2013
MoSQL: More than SQL, but Less than ORM @ PyCon APAC 2013MoSQL: More than SQL, but Less than ORM @ PyCon APAC 2013
MoSQL: More than SQL, but Less than ORM @ PyCon APAC 2013Mosky Liu
 
Advanced jQuery
Advanced jQueryAdvanced jQuery
Advanced jQuerysergioafp
 
Tame Accidental Complexity with Ruby and MongoMapper
Tame Accidental Complexity with Ruby and MongoMapperTame Accidental Complexity with Ruby and MongoMapper
Tame Accidental Complexity with Ruby and MongoMapperGiordano Scalzo
 
MoSQL: More than SQL, but less than ORM
MoSQL: More than SQL, but less than ORMMoSQL: More than SQL, but less than ORM
MoSQL: More than SQL, but less than ORMMosky Liu
 
Dig Deeper into WordPress - WD Meetup Cairo
Dig Deeper into WordPress - WD Meetup CairoDig Deeper into WordPress - WD Meetup Cairo
Dig Deeper into WordPress - WD Meetup CairoMohamed Mosaad
 
Final tagless and cats mtl
Final tagless and cats mtl Final tagless and cats mtl
Final tagless and cats mtl Alexander Zaidel
 
Hacking Your Way to Better Security - ZendCon 2016
Hacking Your Way to Better Security - ZendCon 2016Hacking Your Way to Better Security - ZendCon 2016
Hacking Your Way to Better Security - ZendCon 2016Colin O'Dell
 
Hacking Your Way To Better Security - DrupalCon Baltimore 2017
Hacking Your Way To Better Security - DrupalCon Baltimore 2017Hacking Your Way To Better Security - DrupalCon Baltimore 2017
Hacking Your Way To Better Security - DrupalCon Baltimore 2017Colin O'Dell
 

Mais procurados (20)

Hacking Your Way To Better Security - php[tek] 2016
Hacking Your Way To Better Security - php[tek] 2016Hacking Your Way To Better Security - php[tek] 2016
Hacking Your Way To Better Security - php[tek] 2016
 
Play, Slick, play2-authの間で討死
Play, Slick, play2-authの間で討死Play, Slick, play2-authの間で討死
Play, Slick, play2-authの間で討死
 
Command-Oriented Architecture
Command-Oriented ArchitectureCommand-Oriented Architecture
Command-Oriented Architecture
 
Automatically Spotting Cross-language Relations
Automatically Spotting Cross-language RelationsAutomatically Spotting Cross-language Relations
Automatically Spotting Cross-language Relations
 
Javascript & jQuery: A pragmatic introduction
Javascript & jQuery: A pragmatic introductionJavascript & jQuery: A pragmatic introduction
Javascript & jQuery: A pragmatic introduction
 
Implementation Specifications
Implementation SpecificationsImplementation Specifications
Implementation Specifications
 
Drupal csu-open atriumname
Drupal csu-open atriumnameDrupal csu-open atriumname
Drupal csu-open atriumname
 
DataMapper @ RubyEnRails2009
DataMapper @ RubyEnRails2009DataMapper @ RubyEnRails2009
DataMapper @ RubyEnRails2009
 
DOSUG Intro to JQuery JavaScript Framework
DOSUG Intro to JQuery JavaScript FrameworkDOSUG Intro to JQuery JavaScript Framework
DOSUG Intro to JQuery JavaScript Framework
 
MoSQL: More than SQL, but Less than ORM @ PyCon APAC 2013
MoSQL: More than SQL, but Less than ORM @ PyCon APAC 2013MoSQL: More than SQL, but Less than ORM @ PyCon APAC 2013
MoSQL: More than SQL, but Less than ORM @ PyCon APAC 2013
 
Advanced jQuery
Advanced jQueryAdvanced jQuery
Advanced jQuery
 
Daily notes
Daily notesDaily notes
Daily notes
 
Tame Accidental Complexity with Ruby and MongoMapper
Tame Accidental Complexity with Ruby and MongoMapperTame Accidental Complexity with Ruby and MongoMapper
Tame Accidental Complexity with Ruby and MongoMapper
 
MoSQL: More than SQL, but less than ORM
MoSQL: More than SQL, but less than ORMMoSQL: More than SQL, but less than ORM
MoSQL: More than SQL, but less than ORM
 
Dig Deeper into WordPress - WD Meetup Cairo
Dig Deeper into WordPress - WD Meetup CairoDig Deeper into WordPress - WD Meetup Cairo
Dig Deeper into WordPress - WD Meetup Cairo
 
jQuery introduction
jQuery introductionjQuery introduction
jQuery introduction
 
Final tagless and cats mtl
Final tagless and cats mtl Final tagless and cats mtl
Final tagless and cats mtl
 
Hacking Your Way to Better Security - ZendCon 2016
Hacking Your Way to Better Security - ZendCon 2016Hacking Your Way to Better Security - ZendCon 2016
Hacking Your Way to Better Security - ZendCon 2016
 
Hacking Your Way To Better Security - DrupalCon Baltimore 2017
Hacking Your Way To Better Security - DrupalCon Baltimore 2017Hacking Your Way To Better Security - DrupalCon Baltimore 2017
Hacking Your Way To Better Security - DrupalCon Baltimore 2017
 
Sk.php
Sk.phpSk.php
Sk.php
 

Destaque

What is NetFlow?
What is NetFlow?What is NetFlow?
What is NetFlow?NetHound
 
DPI Vas Experts Linkmeup
DPI Vas Experts LinkmeupDPI Vas Experts Linkmeup
DPI Vas Experts LinkmeupAlexander Fatin
 
Monitoring pg with_graphite_grafana
Monitoring pg with_graphite_grafanaMonitoring pg with_graphite_grafana
Monitoring pg with_graphite_grafanaJan Wieck
 
Will iPython replace bash?
Will iPython replace bash?Will iPython replace bash?
Will iPython replace bash?Roberto Polli
 
Scalable Monitoring & Alerting
Scalable Monitoring & AlertingScalable Monitoring & Alerting
Scalable Monitoring & AlertingFranklin Angulo
 
Programming Under Linux In Python
Programming Under Linux In PythonProgramming Under Linux In Python
Programming Under Linux In PythonMarwan Osman
 
Introducing wizzy - a CLI tool for Grafana
Introducing wizzy - a CLI tool for GrafanaIntroducing wizzy - a CLI tool for Grafana
Introducing wizzy - a CLI tool for GrafanaUTKARSH BHATNAGAR
 
Мониторинг. Опять, rootconf 2016
Мониторинг. Опять, rootconf 2016Мониторинг. Опять, rootconf 2016
Мониторинг. Опять, rootconf 2016Vsevolod Polyakov
 
Torkel Ödegaard (Creator of Grafana) - Grafana at #DOXLON
Torkel Ödegaard (Creator of Grafana) - Grafana at #DOXLONTorkel Ödegaard (Creator of Grafana) - Grafana at #DOXLON
Torkel Ödegaard (Creator of Grafana) - Grafana at #DOXLONOutlyer
 
Python for Linux System Administration
Python for Linux System AdministrationPython for Linux System Administration
Python for Linux System Administrationvceder
 
PHP to Python with No Regrets
PHP to Python with No RegretsPHP to Python with No Regrets
PHP to Python with No RegretsAlex Ezell
 
Real programmers use programming languages (Not shell scripts)
Real programmers use programming languages (Not shell scripts)Real programmers use programming languages (Not shell scripts)
Real programmers use programming languages (Not shell scripts)thedandan
 
ZFS Tutorial USENIX LISA09 Conference
ZFS Tutorial USENIX LISA09 ConferenceZFS Tutorial USENIX LISA09 Conference
ZFS Tutorial USENIX LISA09 ConferenceRichard Elling
 
MPLS (Multi-Protocol Label Switching)
MPLS  (Multi-Protocol Label Switching)MPLS  (Multi-Protocol Label Switching)
MPLS (Multi-Protocol Label Switching)NetProtocol Xpert
 

Destaque (20)

What is NetFlow?
What is NetFlow?What is NetFlow?
What is NetFlow?
 
Graphite
GraphiteGraphite
Graphite
 
Go with the flow
Go with the flowGo with the flow
Go with the flow
 
DPI Vas Experts Linkmeup
DPI Vas Experts LinkmeupDPI Vas Experts Linkmeup
DPI Vas Experts Linkmeup
 
Monitoring pg with_graphite_grafana
Monitoring pg with_graphite_grafanaMonitoring pg with_graphite_grafana
Monitoring pg with_graphite_grafana
 
Will iPython replace bash?
Will iPython replace bash?Will iPython replace bash?
Will iPython replace bash?
 
MPLS-TE Fault Tolerance
MPLS-TE Fault ToleranceMPLS-TE Fault Tolerance
MPLS-TE Fault Tolerance
 
Scalable Monitoring & Alerting
Scalable Monitoring & AlertingScalable Monitoring & Alerting
Scalable Monitoring & Alerting
 
Programming Under Linux In Python
Programming Under Linux In PythonProgramming Under Linux In Python
Programming Under Linux In Python
 
DDoS-bdNOG
DDoS-bdNOGDDoS-bdNOG
DDoS-bdNOG
 
Introducing wizzy - a CLI tool for Grafana
Introducing wizzy - a CLI tool for GrafanaIntroducing wizzy - a CLI tool for Grafana
Introducing wizzy - a CLI tool for Grafana
 
Мониторинг. Опять, rootconf 2016
Мониторинг. Опять, rootconf 2016Мониторинг. Опять, rootconf 2016
Мониторинг. Опять, rootconf 2016
 
Torkel Ödegaard (Creator of Grafana) - Grafana at #DOXLON
Torkel Ödegaard (Creator of Grafana) - Grafana at #DOXLONTorkel Ödegaard (Creator of Grafana) - Grafana at #DOXLON
Torkel Ödegaard (Creator of Grafana) - Grafana at #DOXLON
 
Hacking Cisco
Hacking CiscoHacking Cisco
Hacking Cisco
 
Python for Linux System Administration
Python for Linux System AdministrationPython for Linux System Administration
Python for Linux System Administration
 
Metrics: where and how
Metrics: where and howMetrics: where and how
Metrics: where and how
 
PHP to Python with No Regrets
PHP to Python with No RegretsPHP to Python with No Regrets
PHP to Python with No Regrets
 
Real programmers use programming languages (Not shell scripts)
Real programmers use programming languages (Not shell scripts)Real programmers use programming languages (Not shell scripts)
Real programmers use programming languages (Not shell scripts)
 
ZFS Tutorial USENIX LISA09 Conference
ZFS Tutorial USENIX LISA09 ConferenceZFS Tutorial USENIX LISA09 Conference
ZFS Tutorial USENIX LISA09 Conference
 
MPLS (Multi-Protocol Label Switching)
MPLS  (Multi-Protocol Label Switching)MPLS  (Multi-Protocol Label Switching)
MPLS (Multi-Protocol Label Switching)
 

Semelhante a SQLAlchemy Seminar

Achilles presentation
Achilles presentationAchilles presentation
Achilles presentationDuyhai Doan
 
Desenvolvimento web com Ruby on Rails (parte 3)
Desenvolvimento web com Ruby on Rails (parte 3)Desenvolvimento web com Ruby on Rails (parte 3)
Desenvolvimento web com Ruby on Rails (parte 3)Joao Lucas Santana
 
Montreal Sql saturday: moving data from no sql db to azure data lake
Montreal Sql saturday: moving data from no sql db to azure data lakeMontreal Sql saturday: moving data from no sql db to azure data lake
Montreal Sql saturday: moving data from no sql db to azure data lakeDiponkar Paul
 
Статичный SQL в С++14. Евгений Захаров ➠ CoreHard Autumn 2019
Статичный SQL в С++14. Евгений Захаров ➠  CoreHard Autumn 2019Статичный SQL в С++14. Евгений Захаров ➠  CoreHard Autumn 2019
Статичный SQL в С++14. Евгений Захаров ➠ CoreHard Autumn 2019corehard_by
 
Introduction to Active Record - Silicon Valley Ruby Conference 2007
Introduction to Active Record - Silicon Valley Ruby Conference 2007Introduction to Active Record - Silicon Valley Ruby Conference 2007
Introduction to Active Record - Silicon Valley Ruby Conference 2007Rabble .
 
Introduction to Active Record at MySQL Conference 2007
Introduction to Active Record at MySQL Conference 2007Introduction to Active Record at MySQL Conference 2007
Introduction to Active Record at MySQL Conference 2007Rabble .
 
Uma Abordagem Orientada a Modelos para Modelagem Conceitual de Banco de Dados
Uma Abordagem Orientada a Modelos para Modelagem Conceitual de Banco de DadosUma Abordagem Orientada a Modelos para Modelagem Conceitual de Banco de Dados
Uma Abordagem Orientada a Modelos para Modelagem Conceitual de Banco de DadosCarlos Eduardo Pantoja
 
Where's My SQL? Designing Databases with ActiveRecord Migrations
Where's My SQL? Designing Databases with ActiveRecord MigrationsWhere's My SQL? Designing Databases with ActiveRecord Migrations
Where's My SQL? Designing Databases with ActiveRecord MigrationsEleanor McHugh
 
Miniproject on Employee Management using Perl/Database.
Miniproject on Employee Management using Perl/Database.Miniproject on Employee Management using Perl/Database.
Miniproject on Employee Management using Perl/Database.Sanchit Raut
 
Работа с реляционными базами данных в C++
Работа с реляционными базами данных в C++Работа с реляционными базами данных в C++
Работа с реляционными базами данных в C++corehard_by
 
JQuery In Rails
JQuery In RailsJQuery In Rails
JQuery In RailsLouie Zhao
 
Mongo db mug_2012-02-07
Mongo db mug_2012-02-07Mongo db mug_2012-02-07
Mongo db mug_2012-02-07Will Button
 
Relaxing With CouchDB
Relaxing With CouchDBRelaxing With CouchDB
Relaxing With CouchDBleinweber
 
development, ruby, conferences, frameworks, ruby on rails, confreaks, actsasc...
development, ruby, conferences, frameworks, ruby on rails, confreaks, actsasc...development, ruby, conferences, frameworks, ruby on rails, confreaks, actsasc...
development, ruby, conferences, frameworks, ruby on rails, confreaks, actsasc...ActsAsCon
 
How to leverage what's new in MongoDB 3.6
How to leverage what's new in MongoDB 3.6How to leverage what's new in MongoDB 3.6
How to leverage what's new in MongoDB 3.6Maxime Beugnet
 
Di web tech mail (no subject)
Di web tech mail   (no subject)Di web tech mail   (no subject)
Di web tech mail (no subject)shubhamvcs
 

Semelhante a SQLAlchemy Seminar (20)

Achilles presentation
Achilles presentationAchilles presentation
Achilles presentation
 
Desenvolvimento web com Ruby on Rails (parte 3)
Desenvolvimento web com Ruby on Rails (parte 3)Desenvolvimento web com Ruby on Rails (parte 3)
Desenvolvimento web com Ruby on Rails (parte 3)
 
Montreal Sql saturday: moving data from no sql db to azure data lake
Montreal Sql saturday: moving data from no sql db to azure data lakeMontreal Sql saturday: moving data from no sql db to azure data lake
Montreal Sql saturday: moving data from no sql db to azure data lake
 
Статичный SQL в С++14. Евгений Захаров ➠ CoreHard Autumn 2019
Статичный SQL в С++14. Евгений Захаров ➠  CoreHard Autumn 2019Статичный SQL в С++14. Евгений Захаров ➠  CoreHard Autumn 2019
Статичный SQL в С++14. Евгений Захаров ➠ CoreHard Autumn 2019
 
Introduction to Active Record - Silicon Valley Ruby Conference 2007
Introduction to Active Record - Silicon Valley Ruby Conference 2007Introduction to Active Record - Silicon Valley Ruby Conference 2007
Introduction to Active Record - Silicon Valley Ruby Conference 2007
 
Django - sql alchemy - jquery
Django - sql alchemy - jqueryDjango - sql alchemy - jquery
Django - sql alchemy - jquery
 
Introduction to Active Record at MySQL Conference 2007
Introduction to Active Record at MySQL Conference 2007Introduction to Active Record at MySQL Conference 2007
Introduction to Active Record at MySQL Conference 2007
 
Uma Abordagem Orientada a Modelos para Modelagem Conceitual de Banco de Dados
Uma Abordagem Orientada a Modelos para Modelagem Conceitual de Banco de DadosUma Abordagem Orientada a Modelos para Modelagem Conceitual de Banco de Dados
Uma Abordagem Orientada a Modelos para Modelagem Conceitual de Banco de Dados
 
Where's My SQL? Designing Databases with ActiveRecord Migrations
Where's My SQL? Designing Databases with ActiveRecord MigrationsWhere's My SQL? Designing Databases with ActiveRecord Migrations
Where's My SQL? Designing Databases with ActiveRecord Migrations
 
greenDAO
greenDAOgreenDAO
greenDAO
 
Coding Ajax
Coding AjaxCoding Ajax
Coding Ajax
 
Miniproject on Employee Management using Perl/Database.
Miniproject on Employee Management using Perl/Database.Miniproject on Employee Management using Perl/Database.
Miniproject on Employee Management using Perl/Database.
 
Работа с реляционными базами данных в C++
Работа с реляционными базами данных в C++Работа с реляционными базами данных в C++
Работа с реляционными базами данных в C++
 
JQuery In Rails
JQuery In RailsJQuery In Rails
JQuery In Rails
 
Mongo db mug_2012-02-07
Mongo db mug_2012-02-07Mongo db mug_2012-02-07
Mongo db mug_2012-02-07
 
Relaxing With CouchDB
Relaxing With CouchDBRelaxing With CouchDB
Relaxing With CouchDB
 
development, ruby, conferences, frameworks, ruby on rails, confreaks, actsasc...
development, ruby, conferences, frameworks, ruby on rails, confreaks, actsasc...development, ruby, conferences, frameworks, ruby on rails, confreaks, actsasc...
development, ruby, conferences, frameworks, ruby on rails, confreaks, actsasc...
 
Coding Ajax
Coding AjaxCoding Ajax
Coding Ajax
 
How to leverage what's new in MongoDB 3.6
How to leverage what's new in MongoDB 3.6How to leverage what's new in MongoDB 3.6
How to leverage what's new in MongoDB 3.6
 
Di web tech mail (no subject)
Di web tech mail   (no subject)Di web tech mail   (no subject)
Di web tech mail (no subject)
 

Mais de Yury Yurevich

ekb.py: KISS REST API
ekb.py: KISS REST APIekb.py: KISS REST API
ekb.py: KISS REST APIYury Yurevich
 
ekb.py: Mini Zen of Python
ekb.py: Mini Zen of Pythonekb.py: Mini Zen of Python
ekb.py: Mini Zen of PythonYury Yurevich
 
PyCon UA 2011: Test Infected
PyCon UA 2011: Test InfectedPyCon UA 2011: Test Infected
PyCon UA 2011: Test InfectedYury Yurevich
 
Александр Гладыш — Visual editor for business logic in Lua and JS
Александр Гладыш — Visual editor for business logic in Lua and JSАлександр Гладыш — Visual editor for business logic in Lua and JS
Александр Гладыш — Visual editor for business logic in Lua and JSYury Yurevich
 
Лев Валкин — Кое-что про Erlang
Лев Валкин — Кое-что про ErlangЛев Валкин — Кое-что про Erlang
Лев Валкин — Кое-что про ErlangYury Yurevich
 
Ильшад Хабибуллин — BlueBream
Ильшад Хабибуллин — BlueBreamИльшад Хабибуллин — BlueBream
Ильшад Хабибуллин — BlueBreamYury Yurevich
 
Иван Иноземцев — Fantom
Иван Иноземцев — FantomИван Иноземцев — Fantom
Иван Иноземцев — FantomYury Yurevich
 
Александр Гладыш — Lua
Александр Гладыш — LuaАлександр Гладыш — Lua
Александр Гладыш — LuaYury Yurevich
 
About (unit) testing
About (unit) testingAbout (unit) testing
About (unit) testingYury Yurevich
 
Almost Success Story: Unix to Linux migration
Almost Success Story: Unix to Linux migrationAlmost Success Story: Unix to Linux migration
Almost Success Story: Unix to Linux migrationYury Yurevich
 

Mais de Yury Yurevich (12)

ekb.py: KISS REST API
ekb.py: KISS REST APIekb.py: KISS REST API
ekb.py: KISS REST API
 
ekb.py: Mini Zen of Python
ekb.py: Mini Zen of Pythonekb.py: Mini Zen of Python
ekb.py: Mini Zen of Python
 
PyCon UA 2011: Test Infected
PyCon UA 2011: Test InfectedPyCon UA 2011: Test Infected
PyCon UA 2011: Test Infected
 
Александр Гладыш — Visual editor for business logic in Lua and JS
Александр Гладыш — Visual editor for business logic in Lua and JSАлександр Гладыш — Visual editor for business logic in Lua and JS
Александр Гладыш — Visual editor for business logic in Lua and JS
 
Лев Валкин — Кое-что про Erlang
Лев Валкин — Кое-что про ErlangЛев Валкин — Кое-что про Erlang
Лев Валкин — Кое-что про Erlang
 
Ильшад Хабибуллин — BlueBream
Ильшад Хабибуллин — BlueBreamИльшад Хабибуллин — BlueBream
Ильшад Хабибуллин — BlueBream
 
Иван Иноземцев — Fantom
Иван Иноземцев — FantomИван Иноземцев — Fantom
Иван Иноземцев — Fantom
 
Александр Гладыш — Lua
Александр Гладыш — LuaАлександр Гладыш — Lua
Александр Гладыш — Lua
 
Decorators' recipes
Decorators' recipesDecorators' recipes
Decorators' recipes
 
About Python
About PythonAbout Python
About Python
 
About (unit) testing
About (unit) testingAbout (unit) testing
About (unit) testing
 
Almost Success Story: Unix to Linux migration
Almost Success Story: Unix to Linux migrationAlmost Success Story: Unix to Linux migration
Almost Success Story: Unix to Linux migration
 

Último

Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEarley Information Science
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilV3cube
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Paola De la Torre
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfEnterprise Knowledge
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 

Último (20)

Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of Brazil
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 

SQLAlchemy Seminar

  • 1. SQLAlchemy доступ к реляционным данным в стиле Python Юревич Юрий, http://pyobject.ru Семинар Учебного центра Люксофт, 16 сентября 2008
  • 2. «SQLAlchemy — это Python SQL тулкит и ORM, которые предоставляют разработчику всю мощь и гибкость SQL» http://sqlalchemy.org 2
  • 3. Active Record (Django ORM, Storm) 3
  • 7. Про что (почти) не будет 7
  • 10. Создание таблиц: SQL CREATE TABLE users ( id INTEGER NOT NULL, name VARCHAR(255), PRIMARY KEY (id) ); CREATE TABLE creds ( id INTEGER NOT NULL, user_id INTEGER, login VARCHAR(20), passwd VARCHAR(40), PRIMARY KEY (id), FOREIGN KEY(user_id) REFERENCES users (id) ); 10
  • 11. Создание таблиц: SQLAlchemy meta = MetaData() users = Table('users', meta, Column('id', Integer, primary_key=True), Column('name', Unicode(255)), ) creds = Table('creds', meta, Column('id', Integer, primary_key=True), Column('user_id', Integer, ForeignKey('users.id')), Column('login', String(20)), Column('passwd', String(40)), ) 11
  • 12. MetaData: что умеет Создавать/удалять: ● Всё сразу: – meta.create_all() / meta.drop_all() По отдельности: – users.create() / users.drop() Рефлексия: ● Потаблично: – users = Table('users', meta, autoload=True) Всё сразу: – meta.reflect() Интроспекция: ● meta.tables – 12
  • 13. MetaData: пример из жизни # ... описание схемы def get_indexes(): return [ Index('ix_users_id', users.c.id, unique=True), Index('ix_creds_id', creds.c.id, unique=True), Index('ix_creds_user_id', creds.c.user_id), ] def load(): # ... загрузка данных pass def postload(): for ix in get_indexes(): ix.create() 13
  • 15. Для любителей трехбуквенных сокращений DML (Data Managament Language): ● insert/update/delete – DQL (Data Query Language): ● select – 15
  • 16. Insert Данные указываются при создании ● ins = users.insert(values={'name': u'Jack'}) ins.execute() Данные указываются при выполнении ● ins = users.insert() ins.execute(name=u'Jack') Несколько записей сразу ● ins = users.insert() ins.execute([{'name': u'Jack'}, {'name': u'Ed'}]) Явно указывая соединение ● engine = create_engine('sqlite:///') ins = insert(users) engine.connect().execute(ins, {'name': u'Jack'}) 16
  • 17. Delete Условие — SQLAlchemy SQL expression ● del_ = users.delete(users.c.name==u'Jack') del_.execute() Условие — строка с SQL ● del_ = users.delete('users.name=:user') del_.params({'user': u'Jack'}).execute() 17
  • 18. Select SELECT * FROM users q = users.select() SELECT users.id, users.name FROM users 18
  • 19. Select SELECT id FROM users WHERE name='Jack' q = users.select([users.c.id], users.c.name==u'Jack') SELECT users.id FROM users WHERE users.name=:name 19
  • 20. Select SELECT * FROM users JOIN creds ON creds.user_id=users.id q = users.join(creds).select() SELECT users.id, users.name, creds.id, creds.user_id, creds.login, creds.passwd JOIN creds ON users.id=creds.user_id 20
  • 21. Почему SA SQL Expr? Потому что Python круче SQL ● 21
  • 22. Почему SA SQL Expr? Потому что Python круче SQL ● Генерация SQL на лету: ● q = select([users, creds.c.login], – from_obj=users.join(creds), whereclause=users.c.name==u'Jack') q = users.select() – q = q.where(users.c.name==u'Jack') q = q.column(creds.c.login) q.append_from(join(users, creds)) SELECT users.id, users.name, creds.login – FROM users JOIN creds ON creds.user_id = users.id WHERE users.name = 'Jack' 22
  • 26. Рабочий пример: таблицы в SQL CREATE TABLE users ( CREATE TABLE messages ( id INTEGER NOT NULL, id INTEGER NOT NULL, name VARCHAR(255), subject VARCHAR(255), PRIMARY KEY (id) body TEXT, ); author_id INTEGER, PRIMARY KEY (id), CREATE TABLE creds ( FOREIGN KEY(author_id) id INTEGER NOT NULL, REFERENCES users (id) user_id INTEGER, ); login VARCHAR(20), passwd VARCHAR(20), CREATE TABLE message_recipients ( PRIMARY KEY (id), message_id INTEGER NOT NULL, FOREIGN KEY(user_id) recipient_id INTEGER NOT NULL, REFERENCES users (id) PRIMARY KEY ( message_id, recipient_id), ); FOREIGN KEY(message_id) REFERENCES messages (id), FOREIGN KEY(recipient_id) REFERENCES users (id) ); 26
  • 27. Рабочий пример: Данные users = { u'Jack': ['jack', 'jack-rabbit'], u'Edvard': ['ed'], u'Mary': ['mary'], } messages = ( { 'author': u'Jack', 'recipients': [u'Edvard', u'Mary'], 'title': u'The first', 'body': u'Ha-ha, I'm the first!, }, { 'author': u'Edvard', 'recipients': [u'Jack', u'Mary'], 'title': u'Hey all', 'body': u'Hi, I'm here', }, { 'author': u'Edvard', 'recipients': [u'Mary'], 'title': u'The silence', 'body': u'Why are you ignoring me?', }, { 'author': u'Mary', 'recipients': [u'Jack'], 'title': u'Hi', 'body': u'Hi, Jack, how are you?', }, 27 )
  • 28. Рабочий пример: таблицы в SA SQL Expr users = Table('users', meta, Column('id', Integer, primary_key=True), Column('name', Unicode(255)), ) creds = Table('creds', meta, Column('id', Integer, primary_key=True), Column('user_id', Integer, ForeignKey('users.id')), Column('login', String(20)), Column('passwd', String(20)), ) messages = Table('messages', meta, Column('id', Integer, primary_key=True), Column('subject', Unicode(255)), Column('body', Text), Column('author_id', Integer, ForeignKey('users.id')), ) message_recipients = Table('message_recipients', meta, Column('message_id', Integer, ForeignKey('messages.id'), primary_key=True), Column('recipient_id', Integer, ForeignKey('users.id'), primary_key=True), ) 28
  • 29. Рабочий пример: Mappings Session = scoped_session(sessionmaker(autoflush=False)) class Base(object): def __init__(self, **kwargs): for key, value in kwargs.items(): setattr(self, key, value) class User(Base): pass class Cred(Base): pass class Message(Base): pass Session.mapper(User, users) # (1) Session.mapper(Cred, creds, properties={ # (2) 'user': relation(User, backref='credentials'),}) Session.mapper(Message, messages, properties={ # (3) 'recipients': relation(User, backref='inbox', secondary=message_recipients), 29 'author': relation(User, backref='outbox'),})
  • 30. Рабочий пример: готовность №1 [ 1]>>> import schema as sch [ 2]>>> import mappings as m [ 3]>>> engine = create_engine('sqlite:///example.sqlite') [ 4]>>> sch.meta.bind = engine [ 5]>>> sch.meta.create_all() [ 6]>>> m.Session.bind = engine [ 7]>>> u1 = m.User.query.get(1) [ 8]>>> u1.id <<< 1 [ 9]>>> u1.name <<< u'Jack' [10]>>> u1.credentials <<< [<Cred: jack>, <Cred: jack-rabbit>] [11]>>> u1.outbox <<< [<Message: from Jack to Edvard, Mary (subj: The first)>] 30
  • 31. Рабочий пример: выборки [1]>>> q = m.User.query.filter(User.id>1) [2]>>> print str(q) SELECT users.id AS users_id, users.name AS users_name FROM users WHERE users.id > ? [3]>>> q = q.filter(m.User.name!=None) [4]>>> print str(q) SELECT users.id AS users_id, users.name AS users_name FROM users WHERE users.id > ? AND users.name IS NOT NULL [5]>>> list(q) <<< [<User u'Edvard'>, <User u'Mary'>] [6]>>> q.first() <<< <User u'Edvard'> 31
  • 32. Рабочий пример: выборки (продолжение) [1]>>> rabbit = m.Cred.query. filter_by(login='jack-rabbit').one() [2]>>> rabbit_user = m.User.query. filter(User.credentials.contains(rabbit)). one() [3]>>> rabbit_messages = m.Message.query. filter(or_( Message.author==rabbit_user, Message.recipients.contains(rabbit_user) )) [4]>>> list(rabbit_messages) <<< [<Message: from Jack to Edvard, Mary (subj: The first)>, <Message: from Edvard to Jack, Mary (subj: Hey all)>, <Message: from Mary to Jack (subj: Hi)>] 32
  • 33. Рабочий пример: выборки (хардкор) # Выбрать пользователей, у которых # в исходящих больше одного сообщения [1]>>> sess = m.Session() [2]>>> q = sess.query(m.User, func.count('*')). join(m.Message).group_by(m.User). having(func.count('*')>1) [3]>>> list(q) <<< [(<User u'Edvard'>, 2)] # Выбрать пользователей, у которых # во входящих больше одного сообщения [4]>>> sess = m.Session() [5]>>> q = sess.query(m.User, func.count('*')). join(sch.message_recipients).group_by(m.User). having(func.count('*')>1) [6]>>> list(q) <<< [(<User u'Jack'>, 2), (<User u'Mary'>, 3)] 33
  • 34. Рабочий пример: сессия, unit of work [ 1]>>> engine = create_engine('sqlite:///example.sqlite', echo=True) [ 2]>>> sch.meta.bind = engine [ 3]>>> m.Session.bind = engine [ 4]>>> sess = m.Session() [ 5]>>> jack = m.User.query.filter_by(name=u'Jack').one() 2008-09-14 14:19:11,504 INFO sqlalchemy.engine.base.Engine.0x...ca2c SELECT... [ 6]>>> ed = m.User.query.filter_by(name=u'Edvard').one() 2008-09-14 14:20:22,731 INFO sqlalchemy.engine.base.Engine.0x...ca2c SELECT... [ 7]>>> jack.name = u'Jack Daniels' [ 8]>>> sess.dirty <<< IdentitySet([<User u'Jack Daniels'>]) [ 9]>>> ed.name = u'Edvard Noringthon' [10]>>> sess.dirty <<< IdentitySet([<User u'Edvard Noringthon'>, <User u'Jack Daniels'>]) [11]>>> sess.flush() 2008-09-14 14:21:00,535 INFO sqlalchemy.engine.base.Engine.0x...ca2c UPDATE users SET name=? WHERE users.id = ? 2008-09-14 14:21:00,535 INFO sqlalchemy.engine.base.Engine.0x...ca2c ['Jack Daniels', 1] 2008-09-14 14:21:00,604 INFO sqlalchemy.engine.base.Engine.0x...ca2c UPDATE users SET name=? WHERE users.id = ? 2008-09-14 14:21:00,604 INFO sqlalchemy.engine.base.Engine.0x...ca2c ['Edvard Noringthon', 2] 34
  • 35. users = Table( 'users', meta, ...) class User: pass mapper(users, User) «user» 5 раз, скучно? 35
  • 36. Elixir: ActiveRecord поверх SQLAlchemy Elixir (http://elixir.ematia.de): ● Декларативное описание в стиле Django – События: – До (update, insert, delete) ● После (update, insert, delete) ● Плагины: – acts_as_versioned (автоматическое хранение истории) ● acts_as_encrypted (шифрование колонок) ● associable (аналог Django generic relations) ● ... ● 36
  • 37. Еще вкусности SQLAlchemy «Хитрые» атрибуты: ● Отложенная/непосредственная подгрузка – SQL-выражение как атрибут – Партицирование: ● Вертикальное (часть таблиц в одной БД, часть в другой) – Горизонтальное (шардинг, содержимое одной таблицы – «раскидано» по таблицам/БД) Нетривиальные маппинги: ● Несколько маппингов к одному классу – Маппинг классов к SQL-запросам – ... ● 37
  • 38. Диагноз: нужна ли вам SA Используете другой Используете DB ● ● ORM и счастливы? API2 и «чистый» SQL? Нет, в SQLAlchemy – «много буков», нет Да, SQLAlchemy – смысла даст вам это и много что еще 38
  • 39. Вопросы? ... не успели задать? - шлите почтой: the.pythy@gmail.com 39