Мы уже упоминали сжатие ZIP и сериализацию в разделе «Сериализация данных» главы 9, поэтому в этой главе нам осталось рассмотреть только базы данных.
Глава посвящена библиотекам Python, которые взаимодействуют с реляционными базами данных. Как правило, когда речь идет о базах данных, мы думаем именно о такой их разновидности — они содержат данные, сохраненные в таблицах, мы получаем к ним доступ с помощью SQL.
Мы уже упоминали инструменты для JSON, XML и ZIP-файлов в главе 9, а также сериализацию и XDR, когда говорили о сериализации. Для анализа YAML мы рекомендуем PyYAML () (вы можете получить его с помощью команды pip install pyyaml). В стандартной библиотеке Python также имеются инструменты для работы с файлами CSV, *.netrc, используемыми некоторыми клиентами FTP, файлами *.plist, применяемыми в OS X, а также файлами, содержащими код на диалекте формата INI из Windows с помощью модуля configparser.
Существует также устойчивое хранилище, работающее по принципу «ключ-значение», доступное благодаря модулю shelve из стандартной библиотеки Python. Его бэкенд является наилучшим доступным вариантом менеджера базы данных (dbm — база данных, работающая по принципу «ключ-значение») для вашего компьютера:
>>> import shelve
>>>
>>> with shelve.open('my_shelf') as s:
... s['d'] = {'key': 'value'}
...
>>> s = shelve.open('my_shelf', 'r')
>>> s['d']
{'key': 'value'}
Вы можете узнать, какой бэкенд используете, таким способом:
>>> import dbm
>>> dbm.whichdb('my_shelf')
'dbm.gnu'
Вы также можете загрузить реализацию GNU для dbm для Windows с сайта или сначала проверить ее наличие в менеджере пакетов (brew, apt, yum), а затем попробовать установить с помощью исходного кода dbm ().
API для работы с базами данных в Python (DB-API2) определяет стандартный интерфейс для доступа к базам данных. Он задокументирован в PEP 249 (/), а также в более подробном введении к DB-API (). Практически все драйверы для баз данных в Python отвечают требованиям этого интерфейса, поэтому, если вы хотите обратиться к базе данных с помощью Python, выберите драйвер, позволяющий соединиться с базой данных, которую вы используете, например sqlite3 для базы данных SQLite, psycopg2 для Postgres и MySQL-python для MySQL.
Код, содержащий большое количество строк SQL, а также жестко закодированные столбцы и таблицы, быстро становится неопрятным, подвержен ошибкам, его сложно отлаживать. Библиотеки, перечисленные в табл. 11.1 (за исключением sqlite3, драйвера для SQLite), предлагают уровень абстракции базы данных (database abstraction layer, DAL), который позволяет абстрагироваться от структуры, грамматики и типов данных SQL, чтобы предоставить API.
Поскольку Python — объектно-ориентированный язык, абстракция для базы данных также может реализовать объектно-реляционное отображение (object-relational mapping, ORM), чтобы соотнести объекты Python и базу данных, а также операторы для атрибутов этих классов, которые представляют собой абстрагированную версию SQL в Python.
Все библиотеки, перечисленные в табл. 11.1 (за исключением sqlite3 и Records), предоставляют ORM, их реализации используют один из двух шаблонов: Active Record (записи одновременно представляют абстрагированные данные и взаимодействуют с базой данных) и Data Mapper (один слой взаимодействует с базой данных, еще один слой представляет данные, а между ними имеется функция соотнесения, которая выполняет логику, необходимую для того, чтобы преобразовывать данные между этими слоями (по сути, выполняет логику представления SQL за пределами базы данных)).
При выполнении запросов шаблоны Active Record и Data Mapper ведут себя примерно одинаково, но, работая с Data Mapper, пользователь должен явно указывать имена таблиц, добавлять первичные ключи и создавать вспомогательные таблицы для поддержки отношений «многие-ко-многим» (например, как в чеке — один идентификатор транзакции будет связан с несколькими покупками); при использовании шаблона Active Record эти действия выполняются за кулисами.
Наиболее популярными библиотеками являются sqlite3, SqlAlchemy и Django ORM. Records находится в собственной категории — это скорее клиент SQL, который предоставляет возможность форматирования выводимой информации; оставшиеся библиотеки можно рассматривать как отдельные легковесные версии Django ORM underneath (поскольку все они используют шаблон ActiveRecord), но с разными реализациями и уникальными API.
Таблица 11.1. Библиотеки для работы с базами данных
Библиотека | Лицензия | Причины использовать |
sqlite3 (драйвер, не ORM) | PSFL | Находится в стандартной библиотеке. Подходит для сайтов с низким или умеренным трафиком, для которого требуются более простые типы данных и малое количество запросов, — у него небольшая задержка, поскольку не осуществляется общения по сети. Подходит для изучения SQL или DB-API для Python, а также для прототипирования приложения, работающего с базами данных |
SQLAlchemy | Лицензия MIT | Предоставляет шаблон Data Mapper, имеющий двухуровневый API, верхний уровень похож на ORM API в других библиотеках, нижний уровень работает с таблицами и непосредственно связан с базой данных. Явно дает вам возможность контролировать (с помощью API нижнего уровня) структуру и схемы вашей базы данных; это может быть полезно, если, например, ваши базы данных администрируют не веб-разработчики. Диалекты: SQLite, PostgreSQL, MySQL, Oracle, MS-SQL Server, Firebird и Sybase (также можно зарегистрировать собственный) |
Django ORM | Лицензия BSD | Предоставляет шаблон Active Record, который может неявно сгенерировать инфраструктуру базы данных с помощью определенных пользователем моделей в приложении. Тесно связан с Django. Диалекты: SQLite, PostgreSQL, MySQL и Oracle; также вы можете использовать стороннюю библиотеку: SAP SQL Anywhere, IBM DB2, MS-SQL Server, Firebird или ODBC |
peewee | Лицензия MIT | Предоставляет шаблон Active Record, но он работает, поскольку таблицы, которые вы определяете в ORM, вы увидите в базе данных (плюс столбец для индексирования). Диалекты: SQLite, MySQL и Postgres (а также ваши собственные) |
PonyORM | AGPLv3 | Предоставляет шаблон Active Record, а также интуитивный синтаксис, основанный на генераторе. В сети имеется графический редактор диаграмм «сущность — отношение» (предназначен для рисования модели данных, определяющей таблицы в базе данных, а также их отношения друг с другом), который может быть преобразован в код SQL для создания таблиц. Диалекты: SQLite, MySQL, Postgres и Oracle (а также ваш собственный) |
SQLObject | LGPL | Одним из первых начал использовать шаблон ActiveRecord в Python. Диалекты: SQLite, MySQL, Postgres, Firebird, Sybase, MAX DB, MS-SQL Server (а также ваш собственный) |
Records (интерфейс запросов, не ORM) | Лицензия ISC | Предоставляет простой способ запрашивать базы данных и генерирует документы отчета: SQL на входе, XLS (или JSON, или YAML, или CSV, или LaTex) на выходе. Имеет интерфейс командной строки, который может быть использован для интерактивных запросов или генерации отчетов с помощью одной строки. Использует в качестве бэкенда SQLAlchemy |
В следующих разделах предоставляется дополнительная информация о библиотеках из табл. 11.1.
SQLite — это библиотека, написанная на C. Предоставляет базу данных на базе sqlite3 (). База данных хранится как один файл, по соглашению он имеет расширение *.db. Страница when to use SQLite («Когда использовать SQLite») () говорит, что библиотека используется как бэкенд базы данных для сайтов, имеющих сотни тысяч посещений в день. На странице также приведен список команд SQL, которые понимает SQLite. Вы можете проконсультироваться с quick SQL reference от W3Schools (), чтобы узнать, как использовать эти команды. Рассмотрим пример:
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 (/) — очень популярный тулкит для баз данных. Django имеет возможность переключиться с собственного ORM на SQLAchemy. Это бэкенд для мегаруководства для Flask по созданию собственного блога (). Pandas использует его как SQL ().
SQLAlchemy — это единственная из перечисленных здесь библиотек, следующая шаблону Data Mapper () Мартина Фаулера (Martin Fowler) (вместо более популярного шаблона Active Record, ). В отличие от остальных библиотек, SQLAlchemy предоставляет не только уровень ORM, но и обобщенный API (который называется уровнем Core), предназначенный для написания кода без SQL. Слой ORM находится выше уровня Core, использующего объекты, которые непосредственно соотносятся с лежащей в его основе базой данных. Пользователь должен явно соотносить эти объекты и ORM, поэтому для начала работы потребуется написать больше кода (это может быть сложно для тех, кто только приступил к работе с реляционными базами данных — создавать объекты можно только явно).
SQLAlchemy может работать на Jython и PyPy и поддерживает версии Python от 2.5 до самой свежей. В следующих фрагментах кода показано, что нужно сделать, чтобы создать объекты с отношением «многие-ко-многим». Мы создадим три объекта на уровне ORM: Customer (Покупатель), Cheese (Сыр) и Purchase (Покупка). Один покупатель может сделать много покупок (отношение «многие-к-одному»), а в одной покупке может содержаться множество видов сыра (отношение «многие-ко-многим»). Мы приводим этот пример для того, чтобы показать несоотнесенную таблицу purchases_cheeses (ей не нужно находиться в ORM, поскольку она нужна только для связи между видами сыра и покупками).
Другие ORM создали бы эту таблицу за кулисами — в этом заключается одно из самых заметных различий между SQLAlchemy и другими библиотеками:
Декларативный базовый объект — это метакласс, который перехватывает создание каждой таблицы из 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 (/).
Django ORM (/) — это интерфейс, используемый Django для предоставления доступа к базе данных. Их реализация шаблона Active Record больше всего похожа реализацию шаблона ActiveRecord, написанную на Ruby on Rails.
Он тесно интегрирован с Django, поэтому вы обычно будете использовать его только при создании веб-приложения с помощью Django. Обратите внимание на руководство к Django ORM от Django Girls (), если вы хотите отслеживать процесс сборки веб-приложения.
Если планируете попробовать поработать с Django ORM, не создавая веб-приложение целиком, скопируйте этот скелет проекта с GitHub, чтобы использовать только Django ORM (), и следуйте приведенным инструкциям. Вы можете столкнуться с некоторыми изменениями для разных версий 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 (/) — предоставить тем, кто знает SQL, легковесный способ взаимодействия с базой данных. Что вы видите, то и получаете (вы не будете разрабатывать вручную верхний уровень, который создает абстрактную структуру таблиц за кулисами, как SQLAlchemy; библиотека также не будет волшебным образом создавать нижний уровень под вашими таблицами вроде Django ORM). Ее цель заключается в том, чтобы заполнить другую нишу, — выполнять небольшое количество задач, но работать быстро, просто и по-питонски.
Здесь нет почти ничего «волшебного» за исключением создания первичных ключей для таблиц в том случае, если этого не сделал пользователь. Вы можете создать таблицу следующим образом:
peewee хранит детали конфигурации в пространстве имен Meta, эта идея заимствована у Django.
Связываем каждый объект типа Model с базой данных.
Первичный ключ будет добавлен неявно, если вы не сделаете этого самостоятельно.
Эта строка добавляет атрибут purchases к записям Customer для упрощения доступа, но ничего не делает с таблицами.
Инициализируем данные и добавляем их в базу данных за один шаг с помощью метода create() или же сначала инициализируем их, а затем добавим (существуют настройки конфигурации для управления автоматической отправкой транзакций и вспомогательными программами для них). Это делается за один этап:
Добавьте объект (вроде cat) — и peewee будет использовать его первичный ключ.
В отношении «многие-ко-многим» нет ничего волшебного — просто добавьте новые записи вручную.
Пример запроса выглядит так:
>>> for p in Purchase.select().where(Purchase.purchase_date > d - 1 * day):
... print(p.customer.name, p.purchase_date)
...
Douglas 1971-12-18
Cat 1971-12-19
>>>
>>> from peewee import fn
>>> q = (Cheese
... .select(Cheese.kind, fn.COUNT(Purchase.id).alias('num_purchased'))
... .join(PurchaseCheese)
... .join(Purchase)
... .group_by(Cheese.kind)
... )
>>> for chz in q:
... print(chz.kind, chz.num_purchased)
...
Camembert 2
Red Leicester 1
Вам доступна коллекция надстроек (), содержащая продвинутую поддержку транзакций, поддержку пользовательских функций, которые могут получать данные и выполнять их обработку до помещения в хранилище (например, сжатие или хэширование).
PonyORM (/) применяет другой подход к грамматике запросов: вместо написания языка, похожего на SQL, или булевых выражений он использует синтаксис генератора Python. Также он имеет графический редактор схем, который может генерировать сущности PonyORM. Поддерживает Python версий 2.6+ и 3.3+.
Для того чтобы синтаксис оставался интуитивно понятным, Pony требует, чтобы все отношения между таблицами работали в обоих направлениях — все связанные таблицы должны явно ссылаться друг на друга, например так:
В базе данных Pony с помощью сущности Entity сохраняется состояние объекта, с ее помощью соединяются база данных и сам объект.
Pony использует стандартные типы Python для определения типа столбца — от str до datetime.datetime, в дополнение к определенным пользователем сущностям вроде Purchase, Customer и Cheese.
Здесь используется lambda: Purchase, потому что Purchase еще не определен.
orm.Set(lambda: Purchase) — первая половина определения отношения «один-ко-многим» между Customer и Purchase.
orm.Required(Customer) — вторая половина отношения «один-ко-многим» между Customer и Purchase.
Отношение orm.Set(Cheese), объединенное с orm.Set(lambda: Purchase) на шаге (3), определяет отношение «многие-ко-многим».
После того как мы определили сущности для данных, создание объекта будет выглядеть как и в других библиотеках. Сущности создаются на лету и отправляются с помощью вызова orm.commit():
camembert = Cheese(type='Camembert')
leicester = Cheese(type='Red Leicester')
cat = Customer(name='Cat')
doug = Customer(name='Douglas')
d = datetime.date(1971, 12, 18)
day = datetime.timedelta(1)
Purchase(date=(d - 1 * day), customer=doug, cheeses={camembert, leicester})
Purchase(date=d, customer=cat, cheeses={camembert})
orm.commit()
Запросы в Pony действительно выглядят так, будто написаны на чистом Python:
Так выглядит запрос, созданный с помощью синтаксиса генератора для Python.
Функция orm.count() объединяет объекты путем подсчета.
SQLObject (/) (выпущен в октябре 2002 года) — самый старый ORM в нашем списке. Его реализация шаблона Active Record, а также оригинальная идея перегрузки стандартных операторов (вроде ==, <, <= и т. д.) как способа абстрагирования некоторой логики SQL в Python, которая теперь реализована почти во всех библиотеках ORM, сделали его весьма популярным.
Поддерживает множество баз данных (распространенные системы вроде MySQL, Postgres и SQLite и более экзотические вроде SAP DB, SyBase и MSSQL), но в данный момент — только Python 2.6 и Python 2.7. Его все еще активно сопровождают, но он становится менее распространенным по мере использования SQLAlchemy.
Records () — это минималистичная библиотека SQL, разработанная для отправки необработанных запросов SQL в разные базы данных. Представляет собой объединенные Tablib и SQLAlchemy, для которых написали хороший API и приложение командной строки (ведет себя как клиент SQL, способный выводить YAML, XLS и другие форматы Tablib). Records не собирается заменять библиотеки ORM; обычно он используется для выполнения запросов к базе данных и создания отчетов (например, ежемесячных отчетов в виде электронной таблицы, куда сохраняются последние данные о продажах). Данные могут быть использованы в программе или импортированы в один из многих полезных форматов:
>>> import records
>>> db = records.Database('sqlite:///mydb.db')
>>>
>>> rows = db.query('SELECT * FROM cheese')
>>> print(rows.dataset)
name |price
-------------|-----
red leicester|1.0
wensleydale |2.2
>>>
>>> print(rows.export('json'))
[{"name": "red leicester", "price": 1.0}, {"name": "wensleydale", "price": 2.2}]
Records предлагает инструмент для командной строки, который экспортирует данные с помощью SQL:
$ records 'SELECT * FROM cheese' yaml --url=sqlite:///mydb.db
- {name: red leicester, price: 1.0}
- {name: wensleydale, price: 2.2}
$ records 'SELECT * FROM cheese' xlsx --url=sqlite:///mydb.db > cheeses.xlsx
Существует целая вселенная баз данных not only SQL («не только SQL») — это понятие применимо к любой базе данных, не являющейся традиционной. Если вы заглянете в PyPI, то можете запутаться, поскольку увидите несколько десятков пакетов Python со схожими именами.
Мы рекомендуем искать сведения о том, какая библиотека больше всего подходит для продукта, на основном сайте проекта для Python (например, поищите в Google «Python site:vendorname.com»). Большая часть библиотек предоставляет Python API и руководство для быстрого старта. Рассмотрим несколько примеров.
• MongoDB — это распределенное хранилище документов. Вы можете рассматривать его как гигантский словарь Python (может находиться в кластере), имеющий собственный фильтр и язык запросов. Для получения API для Python обратитесь к странице /.
• Cassandra — это распределенное хранилище таблиц. Предоставляет возможность быстрого поиска и может работать с широкими таблицами, но не предназначено для выполнения объединений — его функция заключается в том, чтобы иметь дубликаты представлений для данных, ключи для которых содержатся в разных столбцах. Для получения более подробной информации об API для Python обратитесь к странице /.
• HBase — это распределенное хранилище столбцов (в этом контексте «хранилище для столбцов» означает, что данные хранятся в виде <идентификатор строки, имя столбца, значение>, что позволяет работать с очень разреженными массивами вроде наборов данных, получаемых от ссылок from и to для сайтов Всемирной паутины). Хранилище создано на основе распределенной файловой системы Hadoop. Для получения более подробной информации об API для Python обратитесь к странице .
• Druid (/) — это распределенное хранилище столбцов, предназначенное для сбора (и опционального объединения перед сохранением) данных о событиях (в этом контексте «хранилище столбцов» означает, что столбцы можно упорядочить и отсортировать, а затем хранилище может быть сжато для получения более высокой скорости ввода/вывода и меньшего отпечатка). По ссылке вы можете найти API для Python на GitHub.
• Redis — это распределенное хранилище, размещающее в памяти данные в формате «ключ-значение». Идея в том, чтобы снизить задержку, отказавшись от выполнения операций чтения с диска/записи на диск. Например, вы можете сохранять результаты выполнения частых запросов для более быстрого поиска в Сети. По адресу приводится список клиентов Python для Redis, который указывает, что предпочитаемым интерфейсом является redis-py, а по ссылке вы можете найти страницу redis-py.
• Couchbase (/) — еще одно распределенное хранилище документов, его API больше похож на SQL (по сравнению с API для MongoDB, который больше похож на JavaScript). По ссылке вы можете найти Python SDK для Couchbase.
• Neo4j — база данных графов, предназначенная для хранения объектов, связанных подобием графов. По ссылке / вы можете найти руководство по Neo4j для Python.
• LMDB (Lightning Memory-mapped Database от Symas) (/) — база данных, хранящая данные в формате «ключ-значение» в файле, отображаемом в памяти. Это означает, что файл необязательно читать с самого начала для того, чтобы дойти до того места, где хранятся данные, поэтому его производительность равна производительности хранилища в памяти. Привязки для Python находятся в библиотеке lmdb (/).
Идея реляционных баз данных предложена в 1970 году Эдгаром Ф. Коддом (Edgar F. Codd), работником компании IBM. Он написал статью «A Relational Model of Data for Large Share Data Banks» (), которой не интересовались до 1977-го, пока Ларри Эллисон (Larry Ellison) не создал компанию (она в итоге стала компанией Oracle), взявшую за основу эту технологию. Другие идеи-конкуренты вроде хранилища, работающие по принципу «ключ-значение», и иерархические модели баз данных игнорировались после успеха реляционных баз данных. Лишь недавно движение not only SQL (NoSQL) возродило идею использовать нереляционные хранилища для кластерных вычислений.
В Python2 это ConfigParser; обратитесь к документации для configparser (), чтобы увидеть точный диалект, с которым работает анализатор.
Библиотека dbm хранит пары ключ-значение в хэш-таблице, находящейся на диске. Точный механизм ее работы зависит от ее бэкенда — gdbm, ndbm или dumb («глупый»). «Глупый» бэкенд реализован в Python и хорошо задокументирован. Про два других вы можете прочитать в руководстве к gdbm (). Для ndbm существует верхняя граница для сохраняемых значений. При открытии файла для записи он блокируется, если (только для gdbm) вы не открываете файл базы данных в режиме ru или wu, и даже тогда обновления могут быть невидимы для других соединений.
Несмотря на то что язык структурированных запросов (Structured Query Language, SQL) является стандартом ISO (), поставщики баз данных сами выбирают, насколько полно его реализовывать, а также могут добавить собственную функциональность. Это означает, что библиотека Python, которая служит драйвером базы данных, должна понимать диалект SQL выбранной вами базы данных.
Эти шаблоны определены в книге Мартина Фаулера (Martin Fowler) Patterns of Enterprise Application Architecture (). Чтобы подробнее узнать о том, из чего состоят ORM проектов Python, рекомендуем прочесть раздел «SQLAlchemy» книги Architecture of Open Source Applications (), а также взглянуть на список ссылок, связанных с ORM для Python, предоставленный FullStack Python: .
Метаклассы для Python хорошо объясняются на Stack Overflow.
Django Girls (/) — благотворительная организация, в которую входят отличные программисты. Предоставляет возможность бесплатного обучения Django в среде, дружелюбной для женщин всего мира.
Контексты транзакций позволяют отменять выполнение, если на промежуточном шаге возникает ошибка.