Автор оригинала: Mike Driscoll.
В первой части этой серии мы пошли, что некоторые могут вызвать метод «SQL-выражения SQL» использования SQLALCHMEY, чтобы взаимодействовать с вашей базой данных. Теория за этим заключается в том, что мы должны учиться менее абстрактным способом делать вещи, прежде чем добраться до более высокого уровня (и более абстрактных) методов. Это верно во многих математических классах, таких как исчисление, в котором вы изучаете долгий путь, чтобы найти стандартное отклонение некоторых калитков, прежде чем узнать о ярлыке.
На второй половину мы будем делать то, что может сказать, это простой способ использовать SQLALCHEMY. Это известен как метод «Объект реляционного» и Официальная документация на самом деле начинается с этого. Эта методология изначально занимает немного больше времени, но во многих отношениях также намного проще следовать.
Привыкание к отображениям данных
Старая школа Робина Мунна Учебное пособие SQLALCHEMY Вызывается этот раздел «Картирование данных», потому что мы будем отображать данные в базе данных на классы Python. Давайте начнем!
from sqlalchemy import create_engine from sqlalchemy import Column, MetaData, Table from sqlalchemy import Integer, String, ForeignKey from sqlalchemy.orm import mapper, sessionmaker #################################################### class User(object): """""" #---------------------------------------------------------------------- def __init__(self, name, fullname, password): """Constructor""" self.name = name self.fullname = fullname self.password = password def __repr__(self): return "" % (self.name, self.fullname, self.password) # create a connection to a sqlite database # turn echo on to see the auto-generated SQL engine = create_engine("sqlite:///tutorial.db", echo=True) # this is used to keep track of tables and their attributes metadata = MetaData() users_table = Table('users', metadata, Column('user_id', Integer, primary_key=True), Column('name', String), Column('fullname', String), Column('password', String) ) email_table = Table('email', metadata, Column('email_id', Integer, primary_key=True), Column('email_address', String), Column('user_id', Integer, ForeignKey('users.user_id')) ) # create the table and tell it to create it in the # database engine that is passed metadata.create_all(engine) # create a mapping between the users_table and the User class mapper(User, users_table)
Первое отличие, чтобы принять к сведению по сравнению с нашими предыдущими примерами, это Пользователь класс. Мы изменили наш оригинальный пример (см. Часть) немного, чтобы соответствовать тому, что на официальной документации, а именно параметры теперь имеются, полное имя и пароль. Остальные должны выглядеть одинаково, пока не доберемся до Mapper утверждение. Этот удобный метод позволяет SQLALCHEMY для отображения пользовательского класса пользователей_табели. Это может показаться не иметь большого значения, но этот метод делает добавление пользователей в базу данных гораздо более простым.
Однако, прежде чем мы доберемся до этого, нам нужно обсудить Декларативный конфигурационный стиль Отказ Хотя стиль выше дает нам гранулированный контроль над столом, Mapper и Class, по большей части нам не нужно, чтобы быть таким сложным. Вот где приходит декларативный стиль. Это делает настройку всего еще проще. Первый декларативный стиль, который я знал, было дополнением для SQLALCHEMY, называемой Эликсир Отказ Этот встроенный декларативный стиль не так полно, как эликсир, но он укормит, потому что у вас нет дополнительной зависимости. Давайте посмотрим, насколько декларативно отличается:
from sqlalchemy import Column, Integer, String, ForeignKey from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import backref, mapper, relation, sessionmaker Base = declarative_base() ######################################################################## class User(Base): """""" __tablename__ = "users" id = Column(Integer, primary_key=True) name = Column(String) fullname = Column(String) password = Column(String) #---------------------------------------------------------------------- def __init__(self, name, fullname, password): """Constructor""" self.name = name self.fullname = fullname self.password = password def __repr__(self): return "" % (self.name, self.fullname, self.password) ######################################################################## class Address(Base): """ Address Class Create some class properties before initilization """ __tablename__ = "addresses" id = Column(Integer, primary_key=True) email_address = Column(String, nullable=False) user_id = Column(Integer, ForeignKey('users.id')) # creates a bidirectional relationship # from Address to User it's Many-to-One # from User to Address it's One-to-Many user = relation(User, backref=backref('addresses', order_by=id)) #---------------------------------------------------------------------- def __init__(self, email_address): """Constructor""" self.email_address = email_address def __repr__(self): return "" % self.email_address # create a connection to a sqlite database # turn echo on to see the auto-generated SQL engine = create_engine("sqlite:///tutorial.db", echo=True) # get a handle on the table object users_table = User.__table__ # get a handle on the metadata metadata = Base.metadata metadata.create_all(engine)
Как видите, почти все сейчас создано в классах. Мы создаем атрибуты класса (которые похожи на глобальные переменные для класса), которые идентифицируют столбцы таблицы. Затем мы создаем то же __init__, что у нас было в исходном примере класса выше. Кроме того, мы подкласс Декларативность_base а не основные объект Отказ Если нам нужен объект таблицы, мы должны вызвать следующий магический метод Пользователь .__ Таблица __ ; И чтобы получить метаданные, нам нужно позвонить Base.Metadata Отказ Это охватывает различия, о которых мы заботимся о. Теперь мы можем посмотреть, как добавить данные в нашу базу данных.
Класс сейчас в сессии
Красота использования реляционного метода объекта для взаимодействия с нашей базой данных может быть показана в нескольких фрагментах быстрого кода. Давайте посмотрим, как мы можем создать ряд:
mike_user = User("mike", "Mike Driscoll", "password") print "User name: %s, fullname: %s, password: %s" % (mike_user.name, mike_user.fullname, mike_user.password)
Как видите, мы можем создавать пользователей с классом пользователя. Мы можем использовать точечную обозначение для доступа к атрибутам, как мы бы в любом другом классе Python. Мы можем даже использовать их для обновления строк. Например, если нам нужно изменить объект пользователя выше, мы сделаем следующее:
# this is how you would change the name field mike_user.fullname = "Mike Dryskull"
Обратите внимание, что ничто из этого не добавит строку в базу данных автоматически, как эти методы вставки, на которых мы смотрели в нашей первой статье. Вместо этого нам нужен объект сеанса для этого. Давайте пройдемся через некоторые основы использования сеанса:
from sqlalchemy.orm import sessionmaker Session = sessionmaker(bind=engine) session = Session() mike_user = User("mike", "Mike Driscoll", "password") session.add(mike_user)
Мы приостановимся здесь, чтобы объяснить, что происходит. Сначала нам нужно импортировать SessionMaker от sqlalchemy.orm И связывайте его с двигателем (технически, вы можете создать сеанс без привязки, но чтобы сделать что-нибудь полезное, вам нужно будет связать его в конце концов). Далее мы создаем экземпляр сеанса. Затем мы создали объект пользователя и добавьте его на сеанс. На данный момент код SQL не был запущен, и транзакция только в ожидании. Чтобы сохранить эту строку, нам нужно позвонить session.commit () или запустить запрос.
Если вам нужно добавить несколько пользователей, вы делаете это:
session.add_all([ User('Mary', 'Mary Wonka', 'foobar'), User('Sue', 'Sue Lawhead', 'xxg527'), User('Fay', 'Fay Ray', 'blah')])
Если вы произошли, чтобы изменить один из атрибутов пользователя после совершения его в базу данных, вы можете использовать Session.dirty Чтобы проверить, какой из них был изменен. Если вам просто нужно знать, какие строки в ожидании, звоните Session.new Отказ Наконец, мы можем использовать Session.Rollback () откат транзакции.
Теперь давайте посмотрим на некоторые образец запросов:
# do a Select all all_users = session.query(User).all() # Select just one user by the name of "mike" our_user = session.query(User).filter_by(name='mike').first() print our_user # select users that match "Mary" or "Fay" users = session.query(User).filter(User.name.in_(['Mary', 'Fay'])).all() print users # select all and print out all the results sorted by id for instance in session.query(User).order_by(User.id): print instance.name, instance.fullname
Нам не нужно проходить каждый из них, поскольку у всех нас есть объяснения в комментариях. Вместо этого мы перейдем к теме присоединения.
Присоединиться к веселью
Есть присоединения, используя Синтаксис выражения SQL Что я не буду покрывать здесь. Скорее, мы будем использовать реляционную методологию объекта. Если вы оглядываетесь в любой из начинающих примеров для создания таблиц, вы заметите, что мы уже настроили соединение с Иностранник объект. Декларативный формат выглядел так:
user_id = Column(Integer, ForeignKey('users.id')) # creates a bidirectional relationship # from Address to User it's Many-to-One # from User to Address it's One-to-Many user = relation(User, backref=backref('addresses', order_by=id))
Посмотрим, как это работает, создавая новый пользователь:
prof = User("Prof", "Prof. Xavier", "fudge") prof.addresses
Из-за Иностранник и Backref Команда, Пользователь Объект имеет адреса атрибут. Если вы запустите этот код, вы увидите, что он пуст. Давайте добавим некоторые адреса! (Примечание. Обязательно добавьте пользователя PROF на сеанс: Session.add (проф))))
prof.addresses = [Address(email_address='profx@dc.com'), Address(email_address='xavier@yahoo.com')]
Увидеть, как было легко? Еще легко получить информацию обратно. Например, если вы хотите получить доступ только к первому адресу, вы бы просто позвонили prof.addresses [0] Отказ Теперь скажем, что вам нужно изменить один из адресов (I.e. сделать обновление). Это так просто, как пирог:
# change the first address prof.addresses[0].email_address = "profx@marvel.com"
Теперь давайте перейдем к выполнению запросов на присоединениях:
for u, a in session.query(User, Address).filter(User.id==Address.user_id).filter(Address.email_address=='xavier@yahoo.com').all(): print u, a
Это один длинный запрос! Я нахожу тех, кто трудно следовать за собой, поэтому я обычно делаю следующее, чтобы облегчить мою мозгу:
sql = session.query(User, Address) sql = sql.filter(User.id==Address.user_id) sql = sql.filter(Address.email_address=='xavier@yahoo.com') for u, a in sql.all(): print u, a
Теперь, для тех из вас, что любят одноинал, в первом примере нет ничего плохого. Он будет производить точно такие же результаты. Я просто случился, чтобы упростить более длинную версию для отладки. Наконец, мы также можем использовать реальное соединение:
from sqlalchemy.orm import join session.query(User).select_from(join(User, Address)).filter(Address.email_address=='xavier@yahoo.com').all()
Это также делает то же самое, что и предыдущие два примера, но более четко. Для получения дополнительной информации о присоединениях с помощью реляционного синтаксиса объекта я рекомендую Официальная документация Отказ
Обертывание
На данный момент вы должны быть в состоянии создать вашу базу данных с таблицами, заполнять таблицы с данными, а также выбирать, обновлять и совершать транзакции в вашу базу данных с помощью SQLALCHEMY. Я надеюсь, что вы нашли этот учебник полезным в понимании этой удивительной технологии.
Примечание. Этот учебник был протестирован на Windows с Python 2.5 и SQLALCHEMY 0.5.8.
Дальнейшее чтение