реклама
Бургер менюБургер меню

Кеннет Рейтц – Автостопом по Python (страница 67)

18

import sqlite3

db = sqlite3.connect('cheese_emporium.db')

db.execute('CREATE TABLE cheese(id INTEGER, name TEXT)')

db.executemany(

····'INSERT INTO cheese VALUES (??)',

····[(1, 'red leicester'),

····(2, 'wensleydale'),

····(3, 'cheddar'),

····]

)

db.commit()

db.close()

Допустимыми типами SQLite являются NULL, INTEGER, REAL, TEXT и BLOB (bytes), также с помощью документации к sqlite3 вы можете зарегистрировать новые типы данных (например, они реализуют тип datetime.datetime, который хранится как TEXT).

SQLAlchemy

SQLAlchemy (http://www.sqlalchemy.org/) — очень популярный тулкит для баз данных. Django имеет возможность переключиться с собственного ORM на SQLAchemy. Это бэкенд для мегаруководства для Flask по созданию собственного блога (http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world). Pandas использует его как SQL (http://bit.ly/pandas-sql-query).

SQLAlchemy — это единственная из перечисленных здесь библиотек, следующая шаблону Data Mapper (http://martinfowler.com/eaaCatalog/dataMapper.html) Мартина Фаулера (Martin Fowler) (вместо более популярного шаблона Active Record, http://martinfowler.com/eaaCatalog/activeRecord.html). В отличие от остальных библиотек, SQLAlchemy предоставляет не только уровень ORM, но и обобщенный API (который называется уровнем Core), предназначенный для написания кода без SQL. Слой ORM находится выше уровня Core, использующего объекты, которые непосредственно соотносятся с лежащей в его основе базой данных. Пользователь должен явно соотносить эти объекты и ORM, поэтому для начала работы потребуется написать больше кода (это может быть сложно для тех, кто только приступил к работе с реляционными базами данных — создавать объекты можно только явно).

SQLAlchemy может работать на Jython и PyPy и поддерживает версии Python от 2.5 до самой свежей. В следующих фрагментах кода показано, что нужно сделать, чтобы создать объекты с отношением «многие-ко-многим». Мы создадим три объекта на уровне ORM: Customer (Покупатель), Cheese (Сыр) и Purchase (Покупка). Один покупатель может сделать много покупок (отношение «многие-к-одному»), а в одной покупке может содержаться множество видов сыра (отношение «многие-ко-многим»). Мы приводим этот пример для того, чтобы показать несоотнесенную таблицу purchases_cheeses (ей не нужно находиться в ORM, поскольку она нужна только для связи между видами сыра и покупками).

Другие ORM создали бы эту таблицу за кулисами — в этом заключается одно из самых заметных различий между SQLAlchemy и другими библиотеками:

Декларативный базовый объект — это метакласс[121], который перехватывает создание каждой таблицы из ORM и определяет соответствующую таблицу на уровне Core.

Объекты на уровне ORM наследуют от декларативного базового объекта.

Это несоотнесенная таблица на слое Core; это не класс, он не наследуется у декларативного базового объекта, соответствует таблице purchases_cheeses в базе данных и нужен для того, чтобы предоставить соотношение «многие-ко-многим» между сырами и идентификаторами покупок.

Сравните ее с соотнесенной таблицей Cheese на уровне ORM. За кулисами таблица Cheese.__table__ создается на основном слое. Она будет соответствовать таблице базы данных cheeses.

Это отношение явно показывает отношение между соотнесенными классами Cheese и Purchase: они связаны друг с другом опосредованно с помощью вторичной таблицы purchases_cheeses (в противоположность непосредственному связыванию с помощью ForeignKey).

back_populates добавляет слушателя событий, поэтому при добавлении нового объекта типа Purchase в Cheese.purchases объект типа Cheese также появится в Purchase.cheeses.

Этот фрагмент — вторая половина реализации отношения «многие-ко-многим».

Таблицы явно созданы с помощью декларативного базового объекта:

from sqlalchemy import create_engine

engine = create_engine('sqlite://')

Base.metadata.create_all(engine)

А теперь взаимодействие, при котором используются объекты слоя ORM, выглядит так же, как и для других библиотек, имеющих ORM:

Вы должны явно вызывать метод commit() для отправки изменений в базу данных.

Объекты, состоящие в отношениях «многие-ко-многим», не добавляются во время создания (их необходимо вручную вносить уже после создания).

Рассмотрим несколько примеров запросов:

Так создается отношение «многие-ко-многим» для таблицы purchases_cheeses, которая не соотносится с высокоуровневым объектом ORM.

Этот запрос считает количество покупок каждого вида сыра.

Для того чтобы узнать больше, обратитесь к документации SQLAlchemy (http://docs.sqlalchemy.org/en/rel_1_0/).

Django ORM

Django ORM (https://docs.djangoproject.com/en/1.9/topics/db/) — это интерфейс, используемый Django для предоставления доступа к базе данных. Их реализация шаблона Active Record больше всего похожа реализацию шаблона ActiveRecord, написанную на Ruby on Rails.

Он тесно интегрирован с Django, поэтому вы обычно будете использовать его только при создании веб-приложения с помощью Django. Обратите внимание на руководство к Django ORM от Django Girls (http://bit.ly/django-orm-tutorial), если вы хотите отслеживать процесс сборки веб-приложения[122].

Если планируете попробовать поработать с Django ORM, не создавая веб-приложение целиком, скопируйте этот скелет проекта с GitHub, чтобы использовать только Django ORM (https://github.com/mick/django_orm_only), и следуйте приведенным инструкциям. Вы можете столкнуться с некоторыми изменениями для разных версий Django. Наш файл settings.py выглядит следующим образом:

# settings.py

DATABASES = {

····'default': {

········'ENGINE': 'django.db.backends.sqlite3',

········'NAME': 'tmp.db',

····}

}

INSTALLED_APPS = ("orm_only",)

SECRET_KEY = "A secret key may also be required."

Каждая абстрагированная таблица в Django ORM является подклассом объекта Django Model. Это выглядит так:

Отношение ForeignKey обозначает отношение «многие-к-одному» — покупатель может сделать много покупок, но покупка связана с одним покупателем. Используйте OneToOneField для создания отношения «один-к-одному».

Используйте ManyToManyField для записи отношения многие-ко-многим.

Далее нужно выполнить команду для сборки таблиц. Активизировав виртуальную среду, в командной строке перейдите в каталог, где находится файл manage.py, и введите следующий код:

(venv)$ python manage.py migrate

После создания таблиц следует добавить данные в базу. Без использования метода instance.save() данные из новой строки не попадут в базу данных:

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

Вы должны добавлять объекты, состоящие в отношениях «многие-ко-многим», отдельно.

Создание запросов с помощью ORM в Django выглядит так:

В Django оператор для фильтрации (gt, greater than — «больше») добавляется после двойного нижнего подчеркивания к атрибуту таблицы purchase_date (Django анализирует его за кулисами).

Двойное нижнее подчеркивание после идентификатора внешнего ключа предоставит доступ к атрибуту соответствующей таблицы.

В случае если вы не видели нотации, можете поместить в скобки длинное выражение и разбить его на несколько строк для удобочитаемости.

Блок annotate набора запросов добавляет дополнительные поля к каждому результату.

peewee

Основная цель peewee (http://docs.peewee-orm.com/en/latest/) — предоставить тем, кто знает SQL, легковесный способ взаимодействия с базой данных. Что вы видите, то и получаете (вы не будете разрабатывать вручную верхний уровень, который создает абстрактную структуру таблиц за кулисами, как SQLAlchemy; библиотека также не будет волшебным образом создавать нижний уровень под вашими таблицами вроде Django ORM). Ее цель заключается в том, чтобы заполнить другую нишу, — выполнять небольшое количество задач, но работать быстро, просто и по-питонски.

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