Изначально Django предполагал работу только с одной базой данных (системное ограничение включающее такие вещи как группа настроек DATABASE_*). В течение всего этого времени явно ощущалась необходимость поддержки возможности работы с несколькими БД. В рамках работы над версией 1.2 в течение Google Summer of Code поддержка нескольких БД была включена в trunk. С этими новшествами связаны как целый ряд внутренних изменений, так и несколько удачных расширений для существующих интерфейсов работы с БД.
Вы пишете следующее:
В конечном итоге все проекты должны будут быть переведены в такой вид, хотя старый формат будет поддерживаться в Django вплоть до версии 1.4. Единственный ключ в словаре DATABASES, имеющий критическое значение, это «default» — «по умолчанию». Если вы используете базу данных, вам необходимо определить базу данных «default».
Теперь, когда вы сообщили Django о всех своих базах данных, надо найти способ сообщить Django о том, как их использовать. Первым изменением интерфейса в этой области является метод using(). using() принимает единственный параметр имя БД (имена БД служат ключами словаря DATABASES), и привязывает QuerySet к этой базе данных. Как и любое другое средство класса QuerySet, он может быть при необходимости поставлен в цепочку (как, например, метод order_by(), обновляющий результаты первого запроса при повторном запросе). По сути, это даёт вам возможность полностью контролировать, откуда будут читаться данные (а при ловком использовании методов create(), delete() и update() даёт даже возможность контролировать запись):
Новые методы работы с данными класса QuerySet delete() и save() принимают дополнительный аргумент using, в который передаётся, опять же, имя БД.
Кроме того, появляется новый метод класса Managers, db_manager(), который тоже принимает имя БД. Его функция по сути близка функции метода using(). Основное различие заключается в следующем: вместо того, чтобы возвращать QuerySet, он возвращает новый Manager. Сценарий его использования делает возможным связать его в цепочку с теми методами класса Managers, которые не возвращают QuerySet (например, такими как create_user() класса UserManager).
master-slave replication, partitioning и sharding. Однако, это не обязательно будет удобно. Вам придётся часто использовать в коде запросы к методу using(), что не лучшим образом совместимо с принципом реиспользуемых приложений Django (именно по этой причине опция using была удалена из класса модели Meta). Кроме того, в некоторых случаях класс QuerySet не полностью определён. Так, например, для получения доступа к данным класса User метод my_obj.user неявно создаст QuerySet, но методу using() будет некуда отправить запрос. Этим и было обусловлено появление концепции «маршрутизатора БД». Маршрутизаторы БД получают всю информацию о запросе, который вы хотите выполнить, и определяют, какую базу необходимо обратиться. Маршрутизаторы задаются в файле настроек в виде списка DATABASE_ROUTERS:
DATABASE_ROUTERS задаётся списком, поскольку маршрутизатор на любой стадии может вернуть значение None и тогда Django перейдет к следующему маршрутизатору из списка. Маршрутизаторы могу определять следующие методы:
В документации Django по работе с несколькими БД, как всегда, приведена масса практических примеров. В том числе приведены примеры, описывающие, как начать применять распространённые паттерны с маршрутизаторами баз данных. Поддержка нескольких баз данных дает огромные преимущества и значительно расширяет области применения Django.
Интерфейс работы с несколькими БД
Наиболее заметное изменение в Django состоит в том, что, вместо того, чтобы писать настройки базы данных таким образом:DATABASE_ENGINE = "postgresql_psycopg2" DATABASE_NAME = "my_big_project" DATABASE_USER = "mario" DATABASE_PASSWORD = "princess_peach"
Вы пишете следующее:
DATABASES = { "default": { "ENGINE": "django.db.backends.postgresql_psycopg2", "NAME": "my_big_project", "USER": "mario", "PASSWORD": "princess_peach", }, "credentials": { "ENGINE": "django.db.backends.oracle", "NAME": "users", } }
В конечном итоге все проекты должны будут быть переведены в такой вид, хотя старый формат будет поддерживаться в Django вплоть до версии 1.4. Единственный ключ в словаре DATABASES, имеющий критическое значение, это «default» — «по умолчанию». Если вы используете базу данных, вам необходимо определить базу данных «default».
Теперь, когда вы сообщили Django о всех своих базах данных, надо найти способ сообщить Django о том, как их использовать. Первым изменением интерфейса в этой области является метод using(). using() принимает единственный параметр имя БД (имена БД служат ключами словаря DATABASES), и привязывает QuerySet к этой базе данных. Как и любое другое средство класса QuerySet, он может быть при необходимости поставлен в цепочку (как, например, метод order_by(), обновляющий результаты первого запроса при повторном запросе). По сути, это даёт вам возможность полностью контролировать, откуда будут читаться данные (а при ловком использовании методов create(), delete() и update() даёт даже возможность контролировать запись):
>>>User.objects.filter(username__startswith="admin").using("credentials")
Новые методы работы с данными класса QuerySet delete() и save() принимают дополнительный аргумент using, в который передаётся, опять же, имя БД.
Кроме того, появляется новый метод класса Managers, db_manager(), который тоже принимает имя БД. Его функция по сути близка функции метода using(). Основное различие заключается в следующем: вместо того, чтобы возвращать QuerySet, он возвращает новый Manager. Сценарий его использования делает возможным связать его в цепочку с теми методами класса Managers, которые не возвращают QuerySet (например, такими как create_user() класса UserManager).
Маршрутизаторы БД
Используя все эти методы, вы получаете возможность реализовать любую систему, использующую несколько баз данных. В том числеDATABASE_ROUTERS = [ "path.to.AuthRouter", "path.to.MasterSlaveRouter", ]
DATABASE_ROUTERS задаётся списком, поскольку маршрутизатор на любой стадии может вернуть значение None и тогда Django перейдет к следующему маршрутизатору из списка. Маршрутизаторы могу определять следующие методы:
- db_for_read
- db_for_write
- allow_relation
- allow_syncdb
В документации Django по работе с несколькими БД, как всегда, приведена масса практических примеров. В том числе приведены примеры, описывающие, как начать применять распространённые паттерны с маршрутизаторами баз данных. Поддержка нескольких баз данных дает огромные преимущества и значительно расширяет области применения Django.