Базы данных
Django официально поддерживает следующие базы данных:
Также есть ряд бекендов баз данных, предоставляемых сторонними разработчиками.
Django пытается поддерживать как можно больше функций на всех бекендах баз данных. Однако не все бекенды баз данных одинаковы, и нам пришлось принять решения по дизайну о том, какие функции поддерживать, а какие предположения можно сделать безопасно.
В этом файле описываются некоторые функции, которые могут быть актуальны для использования Django. Он не предназначен для замены документации или справочных руководств по работе с сервером.
Общие замечания
Персистентные соединения
Персистентные соединения избегают накладных расходов на повторное установление соединения с базой данных в каждом запросе. Они управляются параметром CONN_MAX_AGE, который определяет максимальное время жизни соединения. Его можно задавать независимо для каждой базы данных.
Значение по умолчанию равно 0, сохраняя историческое поведение закрытия соединения с базой данных в конце каждого запроса. Для включения персистентных соединений установите CONN_MAX_AGE на положительное целое число в секундах. Для неограниченных персистентных соединений установите его в None.
Управление соединениями
Django открывает соединение с базой данных при первом выполнении запроса к базе данных. Он сохраняет это соединение открытым и повторно использует его в последующих запросах. Django закрывает соединение, когда оно превышает максимальный срок, определенный параметром CONN_MAX_AGE, или когда оно больше не может быть использовано.
Подробно, Django автоматически открывает соединение с базой данных всякий раз, когда ему нужно, и если у него его еще нет — либо потому, что это первое соединение, либо потому, что предыдущее соединение было закрыто.
В начале каждого запроса Django закрывает соединение, если оно достигло максимального срока действия. Если ваша база данных закрывает бездействующие соединения через некоторое время, вы должны установить CONN_MAX_AGE на меньшее значение, чтобы Django не пытался использовать соединение, которое было закрыто сервером базы данных. (Эта проблема может затрагивать только сайты с очень низкой посещаемостью.)
В конце каждого запроса Django закрывает соединение, если оно достигло максимального срока действия или находится в состоянии необратимой ошибки. Если при обработке запросов произошли какие-либо ошибки базы данных, Django проверяет, работает ли соединение, и закрывает его, если нет. Таким образом, ошибки базы данных затрагивают не более одного запроса; если соединение становится непригодным, следующий запрос получает новое соединение.
Ограничения
Поскольку каждый поток поддерживает собственное соединение, ваша база данных должна поддерживать как минимум столько же одновременных соединений, сколько у вас потоков обработки.
Иногда к базе данных не будет обращаться большинство ваших представлений, например, потому что это база данных внешней системы или благодаря кэшированию. В таких случаях вы должны установить CONN_MAX_AGE на низкое значение или даже на 0, поскольку нет смысла поддерживать соединение, которое маловероятно будет повторно использоваться. Это поможет сохранить небольшим количество одновременных соединений с этой базой данных.
Сервер разработки создает новый поток для каждого запроса, который он обрабатывает, что делает персистентные соединения неэффективными. Не включайте их во время разработки.
Когда Django устанавливает соединение с базой данных, он настраивает соответствующие параметры в зависимости от используемого бекенда. Если вы включите персистентные соединения, эта настройка больше не будет повторяться в каждом запросе. Если вы измените параметры, такие как уровень изоляции соединения или часовой пояс, вы должны либо восстановить значения по умолчанию Django в конце каждого запроса, либо принудительно установить подходящее значение в начале каждого запроса, либо отключить персистентные соединения.
Кодировка
Django предполагает, что все базы данных используют кодировку UTF-8. Использование других кодировок может привести к непредсказуемому поведению, например, к ошибкам «значение слишком длинное» от вашей базы данных для данных, которые допустимы в Django. См. Примечания по конкретной базе данных ниже для получения информации о правильной настройке базы данных.
Примечания по PostgreSQL
Django поддерживает PostgreSQL 9.6 и выше. Требуется psycopg2 2.5.4 или выше, хотя рекомендуется последняя версия.
Настройки соединения с PostgreSQL
Подробности см. в HOST.
Оптимизация конфигурации PostgreSQL
Django требует следующих параметров для своих соединений с базой данных:
-
client_encoding:'UTF8', -
default_transaction_isolation:'read committed'по умолчанию или значение, заданное в параметрах соединения (см. ниже),
Если эти параметры уже имеют правильные значения, Django не будет устанавливать их для каждого нового соединения, что немного улучшает производительность. Вы можете настроить их напрямую в postgresql.conf или более удобно по пользователям базы данных с помощью ALTER ROLE.
Django будет работать нормально без этой оптимизации, но каждое новое соединение будет выполнять дополнительные запросы для установки этих параметров.
Уровень изоляции базы данных
Как и сам PostgreSQL, Django по умолчанию использует уровень изоляции READ COMMITTED уровня изоляции. Если вам нужен более высокий уровень изоляции, например, REPEATABLE READ или SERIALIZABLE, установите его в части OPTIONS вашей конфигурации базы данных в DATABASES:
import psycopg2.extensions
DATABASES = {
# ...
'OPTIONS': {
'isolation_level': psycopg2.extensions.ISOLATION_LEVEL_SERIALIZABLE,
},
}
Примечание
При более высоких уровнях изоляции ваше приложение должно быть готово обрабатывать исключения, возникающие при ошибках сериализации. Этот параметр предназначен для расширенного использования.
Индексы для varchar и text столбцов
При указании db_index=True для полей вашей модели Django обычно выводит одно CREATE INDEX утверждение. Однако если тип базы данных для поля — это varchar или text (например, используется в CharField, FileField, и TextField), то Django создаст дополнительный индекс, который использует соответствующий класс оператора PostgreSQL для столбца. Дополнительный индекс необходим для правильной обработки запросов, которые используют оператор LIKE в своём SQL, как это делается с типами поиска contains и startswith.
Операция миграции для добавления расширений
Если вам нужно добавить расширение PostgreSQL (например, hstore, postgis, и т. д.) с помощью миграции, используйте операцию CreateExtension.
Курсоры на стороне сервера
При использовании QuerySet.iterator(), Django открывает курсор на стороне сервера. По умолчанию PostgreSQL предполагает, что будет извлечено только первые 10% результатов запросов курсора. Планировщик запросов тратит меньше времени на планирование запроса и начинает возвращать результаты быстрее, но это может снизить производительность, если извлекается более 10% результатов. Предположения PostgreSQL о количестве строк, извлеченных для запроса курсора, контролируется параметром cursor_tuple_fraction.
Пулы транзакций и курсоры на стороне сервера
Использование менеджера пулов соединений в режиме пулов транзакций (например, PgBouncer) требует отключения курсоров на стороне сервера для этого соединения.
Курсоры на стороне сервера локальны для соединения и остаются открытыми в конце транзакции, когда AUTOCOMMIT равно True. Следующая транзакция может попытаться извлечь больше результатов из курсора на стороне сервера. В режиме пулов транзакций нет гарантии, что последующие транзакции будут использовать то же соединение. Если используется другое соединение, возникает ошибка, когда транзакция ссылается на курсор на стороне сервера, потому что доступ к курсорам на стороне сервера возможен только в соединении, в котором они были созданы.
Одним из решений является отключение серверных курсоров для подключения в DATABASES, установив DISABLE_SERVER_SIDE_CURSORS в значение True.
Чтобы воспользоваться преимуществами серверных курсоров в режиме пулинга транзакций, можно настроить ещё одно подключение к базе данных для выполнения запросов, использующих серверные курсоры. Это подключение должно быть либо напрямую к базе данных, либо к пулингу подключений в режиме пулинга сессий.
Другой вариант — обернуть каждый QuerySet с использованием серверных курсоров в блоке atomic(), так как он отключает autocommit на время транзакции. Таким образом, серверный курсор будет существовать только на период транзакции.
Ручная настройка значений автоинкрементируемых первичных ключей
Django использует тип данных PostgreSQL SERIAL для хранения автоинкрементируемых первичных ключей. Столбец SERIAL заполняется значениями из последовательности, которая отслеживает следующее доступное значение. Ручная присвоение значения полю с автоинкрементом не обновляет последовательность поля, что может в дальнейшем привести к конфликту. Например:
>>> from django.contrib.auth.models import User >>> User.objects.create(username='alice', pk=1) <User: alice> >>> # The sequence hasn't been updated; its next value is 1. >>> User.objects.create(username='bob') ... IntegrityError: duplicate key value violates unique constraint "auth_user_pkey" DETAIL: Key (id)=(1) already exists.
Если вам необходимо задать такие значения, сбросьте последовательность после этого, чтобы избежать повторного использования значения, которое уже есть в таблице. Команда управления sqlsequencereset генерирует SQL-запросы для этого.
Шаблоны тестовых баз данных
Можно использовать настройку TEST['TEMPLATE'] для указания шаблона (например, 'template0') для создания тестовой базы данных.
Ускорение выполнения тестов с настройками «недолговечных» настроек
Вы можете ускорить выполнение тестов, настроив PostgreSQL для «недолговечности».
Предупреждение
Это опасно: это сделает вашу базу данных более уязвимой к потере или повреждению данных в случае сбоя сервера или отключения электроэнергии. Используйте только на тестовой машине, где вы можете легко восстановить всё содержимое всех баз данных в кластере.
Примечания по MariaDB
Django поддерживает MariaDB 10.2 и выше.
Для использования MariaDB используйте бэкенд MySQL, который используется для обоих. Подробнее см. Примечания по MySQL.
Примечания по MySQL
Поддержка версий
Django поддерживает MySQL 5.7 и выше.
Функция inspectdb Django использует базу данных information_schema, которая содержит подробные данные обо всех схемах баз данных.
Django ожидает, что база данных поддерживает Unicode (кодировка UTF-8) и делегирует ей задачу по принудительному выполнению транзакций и ссылочной целостности. Важно понимать, что последние два не фактически накладываются MySQL при использовании движка хранения MyISAM, см. следующий раздел.
Движки хранения
MySQL имеет несколько движков хранения. Вы можете изменить движок хранения по умолчанию в конфигурации сервера.
Движок хранения по умолчанию в MySQL — InnoDB. Этот движок полностью транзакционный и поддерживает внешние ключи. Он рекомендуется. Однако счётчик автоинкремента InnoDB теряется при перезапуске MySQL, потому что он не запоминает значение AUTO_INCREMENT, вместо этого воссоздавая его как «max(id)+1». Это может привести к непреднамеренному повторному использованию значений AutoField.
Основные недостатки MyISAM заключаются в том, что он не поддерживает транзакции или не накладывает ограничения внешних ключей.
Драйверы MySQL DB API
MySQL имеет несколько драйверов, которые реализуют описанную в PEP 249 базу данных Python API:
- mysqlclient — это собственный драйвер. Он рекомендуется.
- MySQL Connector/Python — это чисто Python-драйвер от Oracle, не требующий библиотеки MySQL-клиента или любых Python-модулей за пределами стандартной библиотеки.
Эти драйверы являются потокобезопасными и предоставляют пулинг подключений.
В дополнение к драйверу DB API Django нуждается в адаптере для доступа к драйверам баз данных из своего ORM. Django предоставляет адаптер для mysqlclient, в то время как MySQL Connector/Python включает свой.
mysqlclient
Django требует mysqlclient 1.4.0 или более поздней версии.
MySQL Connector/Python
MySQL Connector/Python доступен на странице загрузки. Адаптер Django доступен в версиях 1.1.X и более поздних. Он может не поддерживать самые последние релизы Django.
Определения часовых поясов MySQL
Если вы планируете использовать поддержку часовых поясов Django, используйте mysql_tzinfo_to_sql для загрузки таблиц часовых поясов в базу данных MySQL. Это нужно сделать один раз для вашего сервера MySQL, а не для каждой базы данных.
Создание вашей базы данных
Вы можете создать свою базу данных с помощью инструментов командной строки и этого SQL:
CREATE DATABASE <dbname> CHARACTER SET utf8;
Это гарантирует, что все таблицы и столбцы будут по умолчанию использовать UTF-8.
Настройки сортировки
Настройка сортировки столбца управляет порядком сортировки данных, а также тем, какие строки считаются равными. Вы можете указать параметр db_collation для установки имени сортировки столбца для CharField и TextField.
Сортировку также можно настроить на уровне всей базы данных и на уровне каждой таблицы. Это подробно описано в документации MySQL. В таких случаях вы должны изменить настройки сортировки, напрямую взаимодействуя с настройками базы данных или таблицами. Django не предоставляет API для их изменения.
По умолчанию с базой данных UTF-8 MySQL будет использовать сортировку utf8_general_ci. Это приводит к тому, что все сравнения строк на равенство выполняются в регистронезависимом режиме. То есть, "Fred" и "freD" считаются равными на уровне базы данных. Если у вас есть уникальное ограничение на поле, попытка вставки как "aa", так и "AA" в один и тот же столбец будет незаконной, поскольку они сравниваются как равные (и, следовательно, не уникальные) с сортировкой по умолчанию. Если вам нужны регистрозависимые сравнения для конкретного столбца или таблицы, измените столбец или таблицу на использование сортировки utf8_bin.
Обратите внимание, что в соответствии с MySQL Unicode Character Sets, сравнения для сортировки utf8_general_ci выполняются быстрее, но немного менее точно, чем сравнения для utf8_unicode_ci. Если это приемлемо для вашего приложения, вы должны использовать utf8_general_ci, поскольку это быстрее. Если это неприемлемо (например, если вам требуется немецкий порядок словаря), используйте utf8_unicode_ci, поскольку он более точен.
Предупреждение
Наборы форм модели проверяют уникальные поля в регистрозависимом режиме. Таким образом, при использовании регистронезависимой сортировки набор форм с уникальными значениями поля, отличающимися только регистром, пройдёт валидацию, но при вызове save(), будет поднято исключение IntegrityError.
Добавлена поддержка настройки сортировки базы данных для поля.
Подключение к базе данных
См. документацию по настройкам.
Настройки подключения используются в таком порядке:
Другими словами, если вы установите имя базы данных в OPTIONS, это будет иметь приоритет над NAME, которое переопределит всё, что содержится в файле опций MySQL.
Вот пример конфигурации с использованием файла опций MySQL:
# settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'OPTIONS': {
'read_default_file': '/path/to/my.cnf',
},
}
}
# my.cnf
[client]
database = NAME
user = USER
password = PASSWORD
default-character-set = utf8
Несколько других опций подключения MySQLdb могут быть полезны, такие как ssl, init_command, и sql_mode.
Установка sql_mode
Начиная с MySQL 5.7, значение по умолчанию параметра sql_mode содержит STRICT_TRANS_TABLES. Этот параметр преобразует предупреждения в ошибки, когда данные усекаются при вставке, поэтому Django настоятельно рекомендует активировать строгий режим для MySQL, чтобы предотвратить потерю данных (либо STRICT_TRANS_TABLES или STRICT_ALL_TABLES).
Если вам нужно настроить SQL-режим, вы можете установить переменную sql_mode как и другие параметры MySQL: либо в файле конфигурации, либо с помощью записи 'init_command': "SET sql_mode='STRICT_TRANS_TABLES'" в части OPTIONS вашей конфигурации базы данных в DATABASES.
Уровень изоляции
При выполнении одновременных нагрузок, транзакции базы данных из разных сессий (например, отдельных потоков, обрабатывающих разные запросы) могут взаимодействовать друг с другом. Эти взаимодействия зависят от уровня изоляции транзакций каждой сессии. Уровень изоляции транзакций можно установить с помощью записи 'isolation_level' в части OPTIONS вашей конфигурации базы данных в DATABASES. Допустимые значения для этой записи — четыре стандартных уровня изоляции:
'read uncommitted''read committed''repeatable read''serializable'
или None для использования уровня изоляции, настроенного на сервере. Однако Django лучше всего работает и по умолчанию использует «read committed», а не «repeatable read», который используется по умолчанию в MySQL. При использовании «repeatable read» возможна потеря данных. В частности, вы можете столкнуться с ситуациями, когда get_or_create() вызовет IntegrityError, но объект не отобразится в последующем вызове get().
Создание ваших таблиц
При генерации схемы Django не указывает движок хранения, поэтому таблицы будут созданы с использованием движка хранения по умолчанию, настроенного на вашем сервере базы данных. Самое простое решение — установить для вашего сервера базы данных движок хранения по умолчанию на желаемый движок.
Если вы используете хостинг-сервис и не можете изменить движок хранения по умолчанию сервера, у вас есть несколько вариантов.
-
После создания таблиц выполните
ALTER TABLEоператор для преобразования таблицы в новый движок хранения (например, InnoDB):ALTER TABLE <tablename> ENGINE=INNODB;
Это может быть утомительно, если у вас много таблиц.
-
Другой вариант — использовать параметр
init_commandдля MySQLdb до создания таблиц:'OPTIONS': { 'init_command': 'SET default_storage_engine=INNODB', }Это устанавливает движок хранения по умолчанию при подключении к базе данных. После создания ваших таблиц вы должны удалить этот параметр, так как он добавляет запрос, необходимый только при создании таблиц, к каждому подключению к базе данных.
Имена таблиц
Существуют известные проблемы даже в последних версиях MySQL, которые могут изменить регистр имени таблицы при выполнении определённых SQL-запросов в определённых условиях. Рекомендуется использовать имена таблиц в нижнем регистре, если это возможно, чтобы избежать проблем, которые могут возникнуть из-за этого поведения. Django использует имена таблиц в нижнем регистре при автоматическом формировании имён таблиц из моделей, поэтому это, в основном, следует учитывать, если вы переопределяете имя таблицы с помощью параметра db_table.
Сохраняемые точки
Как Django ORM, так и MySQL (при использовании движка хранения InnoDB движка хранения) поддерживают сохраняемые точки базы данных.
Если вы используете движок хранения MyISAM, имейте в виду, что вы получите ошибки, генерируемые базой данных, если попытаетесь использовать методы API транзакций, связанные с сохраняемыми точками. Причина этого в том, что определение движка хранения базы данных MySQL/таблицы — дорогостоящая операция, поэтому было решено, что это не стоит того, чтобы динамически преобразовывать эти методы в no-op в зависимости от результатов такого определения.
Примечания по конкретным полям
Поля символьных строк
Любые поля, хранящиеся с VARCHAR типами столбцов, могут иметь max_length ограничение до 255 символов, если вы используете unique=True для поля. Это влияет на CharField, SlugField. Более подробную информацию см. в документации MySQL.
TextField ограничения
MySQL может индексировать только первые N символов BLOB или TEXT столбца. Поскольку TextField не имеет определённой длины, вы не можете отметить его как unique=True. MySQL сообщит об ошибке: «Столбец BLOB/TEXT <db_column> используется в спецификации ключа без длины ключа».
Поддержка дробных секунд для полей Time и DateTime
MySQL может хранить дробные секунды, при условии, что определение столбца включает указание дробной части (например, DATETIME(6)).
Django не будет обновлять существующие столбцы, чтобы включить дробные секунды, если сервер базы данных их поддерживает. Если вы хотите включить их в существующей базе данных, вам нужно будет либо вручную обновить столбец в целевой базе данных, выполнив команду:
ALTER TABLE `your_table` MODIFY `your_datetime_column` DATETIME(6)
или используя операцию RunSQL в миграции данных.
TIMESTAMP столбцы
Если вы используете устаревшую базу данных, содержащую TIMESTAMP столбцы, вы должны установить USE_TZ = False для предотвращения повреждения данных. inspectdb сопоставляет эти столбцы с DateTimeField и если вы включите поддержку часовых поясов, MySQL и Django будут пытаться преобразовать значения из UTC в локальное время.
Блокировка строк с помощью QuerySet.select_for_update()
MySQL и MariaDB не поддерживают некоторые опции для SELECT ... FOR UPDATE оператора. Если select_for_update() используется с неподдерживаемой опцией, то возникает NotSupportedError.
| Опция | MariaDB | MySQL |
|---|---|---|
SKIP LOCKED | X (≥8.0.1) | |
NOWAIT | X (≥10.3) | X (≥8.0.1) |
OF | X (≥8.0.1) | |
NO KEY |
При использовании select_for_update() в MySQL убедитесь, что вы фильтруете набор запросов по набору полей, содержащихся в уникальных ограничениях, или только по полям, охваченным индексами. В противном случае эксклюзивная блокировка записи будет приобретена на всей таблице на всё время выполнения транзакции.
Автоматическое преобразование типов может привести к неожиданным результатам
При выполнении запроса к строковому типу, но с целочисленным значением, MySQL преобразует типы всех значений в таблице в целочисленный тип перед выполнением сравнения. Если ваша таблица содержит значения 'abc', 'def', и вы запрашиваете WHERE mycolumn=0, обе строки будут совпадать. Аналогично, WHERE mycolumn=1 будет совпадать со значением 'abc1'. Поэтому поля строкового типа, включённые в Django, всегда преобразуют значение в строку перед использованием в запросе.
Если вы реализуете пользовательские поля модели, которые наследуются от Field напрямую, переопределяете get_prep_value(), или используете RawSQL, extra() или raw(), вы должны убедиться, что выполняете соответствующее приведение типов.
Примечания к SQLite
Django поддерживает SQLite 3.9.0 и более поздние версии.
SQLite предоставляет отличную альтернативу для разработки приложений, которые в основном предназначены для чтения или требуют меньшего объема установки. Однако, как и во всех базах данных, существуют некоторые различия, специфичные для SQLite, о которых вам следует знать.
Сопоставление подстрок и чувствительность к регистру
Для всех версий SQLite существует несколько неинтуитивное поведение при попытке сопоставить некоторые типы строк. Это происходит при использовании фильтров iexact или contains в наборах запросов. Поведение делится на два случая:
1. Для сопоставления подстрок все совпадения выполняются без учета регистра. То есть фильтр, такой как filter(name__contains="aa") будет соответствовать имени "Aabb".
2. Для строк, содержащих символы за пределами диапазона ASCII, все точные соответствия строк выполняются с учетом регистра, даже когда в запрос передаются параметры для поиска без учета регистра. Таким образом, фильтр iexact будет вести себя точно так же, как фильтр exact в этих случаях.
Некоторые возможные обходные пути описаны на sqlite.org, но они не используются в стандартном SQLite бэкенде Django, поскольку их интеграция будет довольно сложной для надежной работы. Таким образом, Django предоставляет стандартное поведение SQLite, и вы должны об этом помнить при выполнении фильтрации без учета регистра или подстрок.
Обработка десятичных чисел
В SQLite нет реального внутреннего типа данных decimal. Десятичные значения внутренне преобразуются в тип данных REAL (8-байтовое число с плавающей точкой IEEE), как объяснено в документации типов данных SQLite, поэтому они не поддерживают корректное округление десятичных чисел с плавающей точкой.
Ошибка «База данных заблокирована»
SQLite предназначен для того, чтобы быть легкой базой данных, и поэтому не может поддерживать высокий уровень конкурентности. Ошибки OperationalError: database is locked указывают на то, что ваше приложение испытывает более высокую конкурентность, чем sqlite может обработать по умолчанию. Эта ошибка означает, что один поток или процесс имеет эксклюзивную блокировку соединения с базой данных, а другой поток истек время ожидания освобождения блокировки.
В Python wrapper для SQLite есть значение таймаута по умолчанию, которое определяет, как долго второй поток может ожидать освобождения блокировки, прежде чем истечет время ожидания и будет выброшена ошибка OperationalError: database
is locked.
Если вы получаете эту ошибку, вы можете решить ее, выполнив следующие действия:
- Переключитесь на другой бэкенд базы данных. В какой-то момент SQLite становится слишком «легким» для реальных приложений, и подобные ошибки конкурентности указывают на то, что вы достигли этого момента.
- Перепишите свой код, чтобы уменьшить конкурентность и убедиться, что транзакции базы данных имеют короткий срок жизни.
-
Увеличьте значение таймаута по умолчанию, задав параметр базы данных
timeout:'OPTIONS': { # ... 'timeout': 20, # ... }Это позволит SQLite подождать немного дольше, прежде чем выбросить ошибки «база данных заблокирована»; это не решит их.
QuerySet.select_for_update() не поддерживается
SQLite не поддерживает синтаксис SELECT ... FOR UPDATE. Вызов этой функции не окажет никакого эффекта.
Стиль параметров «pyformat» в запросах raw не поддерживается
Для большинства бэкендов запросы raw (Manager.raw() или cursor.execute()) могут использовать стиль параметров «pyformat», где заполнитель в запросе задается как '%(name)s', а параметры передаются в виде словаря, а не списка. SQLite не поддерживает это.
Изоляция при использовании QuerySet.iterator()
В Изоляция в SQLite есть особые моменты при изменении таблицы во время итерации по ней с использованием QuerySet.iterator(). Если строка добавляется, изменяется или удаляется в цикле, то эта строка может или не может появиться или может появиться дважды в последующих результатах, полученных из итератора. Ваш код должен обрабатывать это.
Включение расширения JSON1 в SQLite
Для использования JSONField в SQLite, необходимо включить расширение JSON1 в библиотеке Python’s sqlite3. Если расширение не включено в вашей установке, будет выброшена системная ошибка (fields.E180).
Чтобы включить расширение JSON1, вы можете следовать инструкциям на странице вики.
Примечания к Oracle
Django поддерживает Oracle Database Server версии 12.2 и выше. Требуется версия 6.0 или выше Python драйвера cx_Oracle.
Для работы команды python manage.py migrate, пользователю вашей Oracle базы данных необходимо иметь права для выполнения следующих команд:
- CREATE TABLE
- CREATE SEQUENCE
- CREATE PROCEDURE
- CREATE TRIGGER
Для запуска набора тестов проекта пользователю обычно требуются следующие дополнительные права:
- CREATE USER
- ALTER USER
- DROP USER
- CREATE TABLESPACE
- DROP TABLESPACE
- CREATE SESSION WITH ADMIN OPTION
- CREATE TABLE WITH ADMIN OPTION
- CREATE SEQUENCE WITH ADMIN OPTION
- CREATE PROCEDURE WITH ADMIN OPTION
- CREATE TRIGGER WITH ADMIN OPTION
Хотя роль RESOURCE имеет необходимые права CREATE TABLE, CREATE SEQUENCE, CREATE PROCEDURE, и CREATE TRIGGER, а пользователю, которому предоставлены права RESOURCE WITH ADMIN OPTION могут предоставлять права RESOURCE, такой пользователь не может предоставлять отдельные права (например, CREATE TABLE), и, следовательно, RESOURCE WITH ADMIN OPTION обычно недостаточно для запуска тестов.
Некоторые наборы тестов также создают представления или материализованные представления; для их запуска пользователю также требуются права CREATE VIEW WITH ADMIN OPTION и CREATE MATERIALIZED VIEW WITH ADMIN OPTION. В частности, это необходимо для собственного набора тестов Django.
Все эти права включены в роль DBA, которая подходит для использования в частной базе данных разработчика.
Бэкенд Oracle базы данных использует пакеты SYS.DBMS_LOB и SYS.DBMS_RANDOM, поэтому вашему пользователю потребуются права на выполнение операций с ними. Обычно он доступен всем пользователям по умолчанию, но если это не так, вам нужно предоставить такие разрешения:
GRANT EXECUTE ON SYS.DBMS_LOB TO user; GRANT EXECUTE ON SYS.DBMS_RANDOM TO user;
Подключение к базе данных
Для подключения с использованием имени службы вашей Oracle базы данных, ваш файл settings.py должен выглядеть примерно так:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.oracle',
'NAME': 'xe',
'USER': 'a_user',
'PASSWORD': 'a_password',
'HOST': '',
'PORT': '',
}
}
В этом случае вы должны оставить как HOST, так и PORT пустыми. Однако, если вы не используете файл tnsnames.ora или подобный способ именования и хотите подключиться с использованием SID («xe» в данном примере), тогда заполните как HOST, так и PORT, как показано ниже:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.oracle',
'NAME': 'xe',
'USER': 'a_user',
'PASSWORD': 'a_password',
'HOST': 'dbprod01ned.mycompany.com',
'PORT': '1540',
}
}
Вы должны либо указать как HOST, так и PORT, либо оставить их пустыми. Django будет использовать другой дескриптор подключения в зависимости от этого выбора.
Полный DSN и Easy Connect
Полная строка DSN или Easy Connect может быть использована в NAME, если как HOST, так и PORT пусты. Этот формат требуется при использовании RAC или подключаемых баз данных без tnsnames.ora, например.
Пример строки Easy Connect:
'NAME': 'localhost:1521/orclpdb1',
Пример полной строки DSN:
'NAME': (
'(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521))'
'(CONNECT_DATA=(SERVICE_NAME=orclpdb1)))'
),
Параметр многопоточности
Если вы планируете запускать Django в многопоточной среде (например, Apache с использованием модуля MPM по умолчанию на любой современной операционной системе), то вы обязательно должны установить параметр threaded вашей конфигурации Oracle базы данных в значение True:
'OPTIONS': {
'threaded': True,
},
Отсутствие этого может привести к сбоям и другому странному поведению.
INSERT … RETURNING INTO
По умолчанию, бэкенд Oracle использует предложение RETURNING INTO для эффективного получения значения AutoField при вставке новых строк. Это поведение может привести к DatabaseError в некоторых необычных ситуациях, таких как вставка в удалённую таблицу или в представление с триггером INSTEAD OF. Предложение RETURNING INTO можно отключить, установив опцию use_returning_into конфигурации базы данных на False.
'OPTIONS': {
'use_returning_into': False,
},
В этом случае бэкенд Oracle будет использовать отдельный запрос SELECT для получения значений AutoField.
Проблемы с именами
Oracle накладывает ограничение на длину имени в 30 символов. Для этого бэкенд обрезает идентификаторы базы данных, чтобы они соответствовали длине, заменяя последние четыре символа усечённого имени повторяющимся значением MD5. Кроме того, бэкенд преобразует идентификаторы базы данных в верхний регистр.
Чтобы предотвратить эти преобразования (это обычно необходимо только при работе с устаревшими базами данных или при доступе к таблицам, которые принадлежат другим пользователям), используйте имя в кавычках в качестве значения для db_table:
class LegacyModel(models.Model):
class Meta:
db_table = '"name_left_in_lowercase"'
class ForeignModel(models.Model):
class Meta:
db_table = '"OTHER_USER"."NAME_ONLY_SEEMS_OVER_30"'
Имена в кавычках также можно использовать с другими поддерживаемыми базами данных Django; за исключением Oracle, однако, кавычки не имеют эффекта.
При запуске migrate, может возникнуть ошибка ORA-06552, если некоторые ключевые слова Oracle используются в качестве имени поля модели или значения опции db_column. Django приводит все идентификаторы, используемые в запросах, в кавычки, чтобы предотвратить большинство таких проблем, но эта ошибка всё же может возникнуть, когда тип данных Oracle используется в качестве имени столбца. В частности, следует избегать использования имён date, timestamp, number или float в качестве имени поля.
NULL и пустые строки
Django обычно предпочитает использовать пустую строку ('') вместо NULL, но Oracle обрабатывает оба значения одинаково. Чтобы обойти это, бэкенд Oracle игнорирует явную опцию null для полей, которые могут иметь пустую строку в качестве значения, и генерирует DDL, как если бы это было null=True. При извлечении данных из базы данных предполагается, что значение NULL в одном из этих полей на самом деле означает пустую строку, и данные неявно преобразуются в соответствии с этим предположением.
TextField ограничения
Бэкенд Oracle хранит TextFields в виде столбцов NCLOB. Oracle накладывает некоторые ограничения на использование таких столбцов LOB в целом:
- Столбцы LOB не могут использоваться в качестве первичных ключей.
- Столбцы LOB не могут использоваться в индексах.
- Столбцы LOB не могут использоваться в списке
SELECT DISTINCT. Это означает, что попытка использовать методQuerySet.distinctдля модели, которая включает столбцыTextField, приведёт к ошибкеORA-00932при работе с Oracle. В качестве обходного решения используйте методQuerySet.deferв сочетании сdistinct(), чтобы предотвратить включение столбцовTextFieldв списокSELECT DISTINCT.
Наследование встроенных бэкендов баз данных
Django поставляется со встроенными бэкендами баз данных. Вы можете наследоваться от существующих бэкендов баз данных, чтобы изменить их поведение, функциональность или конфигурацию.
Предположим, например, что вам нужно изменить единственный параметр базы данных. Сначала нужно создать новую директорию с модулем base в ней. Например:
mysite/
...
mydbengine/
__init__.py
base.py
Модуль base.py должен содержать класс под названием DatabaseWrapper, который наследуется от существующего движка из модуля django.db.backends. Вот пример наследования от движка PostgreSQL для изменения класса функциональности allows_group_by_selected_pks_on_model:
from django.db.backends.postgresql import base, features
class DatabaseFeatures(features.DatabaseFeatures):
def allows_group_by_selected_pks_on_model(self, model):
return True
class DatabaseWrapper(base.DatabaseWrapper):
features_class = DatabaseFeatures
Наконец, необходимо указать DATABASE-ENGINE в вашем файле settings.py:
DATABASES = {
'default': {
'ENGINE': 'mydbengine',
...
},
}
Список текущих движков баз данных можно посмотреть в django/db/backends.
Использование стороннего бэкенда базы данных
Помимо официально поддерживаемых баз данных, существуют сторонние бэкенды, которые позволяют использовать другие базы данных с Django:
Поддерживаемые версии Django и возможности ORM этих неофициальных бэкендов значительно различаются. Вопросы, касающиеся конкретных возможностей этих неофициальных бэкендов, а также запросы по поддержке, следует направлять в каналы поддержки каждого стороннего проекта.
© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/3.2/ref/databases/