Выбрать главу

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 выглядит следующим образом:

вернуться

121

Метаклассы для Python хорошо объясняются на Stack Overflow.

вернуться

122

Django Girls (https://djangogirls.org/) — благотворительная организация, в которую входят отличные программисты. Предоставляет возможность бесплатного обучения Django в среде, дружелюбной для женщин всего мира.