Базы данных
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 10 и выше. Требуется psycopg2 2.5.4 или выше, хотя рекомендуется использовать последнюю версию.
Настройки подключения к PostgreSQL
Подробности см. в HOST.
Чтобы подключиться с помощью имени службы из файла службы подключения и пароля из файла паролей , вы должны указать их в части OPTIONS вашей конфигурации базы данных в DATABASES:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'OPTIONS': {
'service': 'my_service',
'passfile': '.my_pgpass',
},
}
}
[my_service] host=localhost user=USER dbname=NAME port=5432
localhost:5432:NAME:USER:PASSWORD
Была добавлена поддержка подключения по имени службы и указание файла паролей.
Оптимизация конфигурации 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.
Серверные курсоры PostgreSQL
При использовании 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 имеет несколько драйверов, которые реализуют Python Database API, описанную в PEP 249:
- 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.
Настройки сортировки MySQL
Настройка сортировки столбца контролирует порядок сортировки данных, а также то, какие строки сравниваются как равные. Вы можете указать параметр db_collation для установки имени сортировки столбца для CharField и TextField.
Сортировка также может быть установлена на уровне всей базы данных и на уровне каждой таблицы. Это подробно документировано в документации MySQL. В таких случаях необходимо установить сортировку, непосредственно изменяя настройки базы данных или таблиц. Django не предоставляет API для их изменения.
По умолчанию в базе данных UTF-8 MySQL будет использовать сортировку utf8_general_ci. Это приводит к тому, что все сравнения строк на равенство выполняются в регистронезависимом режиме. То есть, "Fred" и "freD" считаются равными на уровне базы данных. Если у вас есть уникальное ограничение на поле, попытка вставить как "aa" , так и "AA" в один и тот же столбец будет незаконной, так как они сравниваются как равные (и, следовательно, не уникальные) с сортировкой по умолчанию. Если вам нужны регистрозависимые сравнения для определенного столбца или таблицы, измените столбец или таблицу на использование сортировки utf8_bin.
Обратите внимание, что согласно наборам символов MySQL Unicode, сравнения для сортировки 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" вместо по умолчанию в MySQL "repeatable read". Потеря данных возможна при использовании "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 является дорогостоящей операцией, поэтому было решено, что не стоит динамически преобразовывать эти методы в недействующие действия на основе результатов такого определения.
Примечания по отдельным полям
Поля символьных данных
Любые поля, которые хранятся с типами столбцов 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 (≥10.6) | 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’s 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 sqlite3. Если расширение не включено в вашей установке, будет возбуждена системная ошибка (fields.E180).
Для включения расширения JSON1 вы можете следовать инструкциям на странице вики.
Примечания по Oracle
Django поддерживает Oracle Database Server версии 19c и выше. Требуется версия 7.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 и Простое подключение
Строка полного DSN или простого подключения может быть использована в NAME, если и HOST, и PORT пустые. Этот формат требуется при использовании RAC или подключенных баз данных без tnsnames.ora, например.
Пример строки простого подключения:
'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/4.0/ref/databases/