Базы данных¶
Django официально поддерживает следующие базы данных:
Существует также ряд бэкэндов баз данных, предоставляемых третьими лицами.
Django пытается поддерживать возможности различных бэкендов по максимуму. Однако, базы данных работают по разному, и нам приходится принимать решение какие возможности поддерживать, чтобы они безопасно работали для всех бэкендов.
В этом файле описаны некоторые функции, которые могут иметь отношение к использованию Django. Он не предназначен для замены документации или справочных руководств по конкретному серверу.
Общие замечания¶
Постоянные соединения с базой данных¶
Постоянные соединения позволяют избежать затрат на повторное установление соединения с базой данных в каждом HTTP-запросе. Они управляются параметром CONN_MAX_AGE, который определяет максимальное время жизни соединения. Его можно установить независимо для каждой базы данных.
Значение по умолчанию — «0», сохраняя историческое поведение закрытия соединения с базой данных в конце каждого запроса. Чтобы включить постоянные соединения, установите для CONN_MAX_AGE положительное целое число секунд. Для неограниченных постоянных подключений установите значение «Нет».
Управление соединениями с базой данных¶
Django выполняет подключение к базе данных при первом запросе. Он держит соединение и использует его для последующих запросов. Django закрывает соединение по истечению CONN_MAX_AGE, или когда оно не может быть больше использовано.
Точнее, Django автоматически создаете соединение с базой данных, если оно необходимо, и нет открытого соединения, потому что это первое соединение, или предыдущее было закрыто.
В начале каждого запроса Django закрывает соединение, если истек его срок. Если ваша база данных закрывает соединение после определенного времени, вам следует указать меньшее значение в CONN_MAX_AGE, чтобы Django не пытался использовать закрытое соединение. (Эта проблема может возникнуть только на сайтах с низким трафиком.)
В конце каждого запроса Django закрывает соединение, если оно достигло максимального возраста или находится в состоянии неисправимой ошибки. Если при обработке запросов возникли какие-либо ошибки базы данных, Django проверяет, работает ли соединение, и закрывает его, если нет. Таким образом, ошибки базы данных затрагивают не более одного запроса на каждый рабочий поток приложения; если соединение становится непригодным для использования, следующий запрос получает новое соединение.
Установка CONN_HEALTH_CHECKS в True может использоваться для повышения надежности повторного использования соединения и предотвращения ошибок, когда соединение было закрыто сервером базы данных, который теперь готов принимать и обслуживать новые соединения, например после перезапуска сервера базы данных. Проверка работоспособности выполняется только один раз для каждого запроса и только в том случае, если во время обработки запроса осуществляется доступ к базе данных.
Предостережения¶
Так как каждый поток использует отдельное подключение, ваша база данных должна поддерживать необходимое количество соединений.
В некоторых случаях большинство представлений могут не использовать базу данных, например, это база данных внешней системы, или благодаря кэшированию. В таких случаях укажите небольшое значение в CONN_MAX_AGE или 0, чтобы не поддерживать соединение, которое почти не используется. Это позволит уменьшить количество одновременных подключений к базе данных.
Сервер для разработки создает отдельны поток для каждого запроса, по этому нет смысла использовать постоянные подключения во время разработки.
При подключении к базе данных, устанавливаются различные параметры подключения в соответствии с используемым бэкендом. При постоянном соединении это не будет выполняться при каждом запросе. Если вы измените параметры подключения, например, уровень изоляции транзакций или часовой пояс, вам следует восстановить параметры по умолчанию после обработки запроса, или устанавливать в начале каждого запроса, или отключить постоянные соединения.
Если соединение создается в ходе длительного процесса, вне цикла запроса-ответа Django, оно будет оставаться открытым до тех пор, пока оно не будет явно закрыто или не наступит тайм-аут. Вы можете использовать django.db.close_old_connections(), чтобы закрыть все старые или непригодные для использования соединения.
Кодировка¶
Django предполагает, что все базы данных используют UTF-8. Использование другой кодировки может привести к неожиданному поведению, например ошибке «value too long», в то время, как данные правильны для Django. Смотрите ниже как настраивать различные базы данных.
PostgreSQL¶
Django поддерживает PostgreSQL 13 и выше. Требуется psycopg 3.1.8+ или psycopg2 2.8.4+, хотя рекомендуется последняя версия psycopg 3.1.8+.
Примечание
Поддержка psycopg2, скорее всего, будет прекращена и прекращена в какой-то момент в будущем.
Настройки подключения PostgreSQL¶
Смотрите подробности в описании HOST.
Чтобы подключиться с использованием имени службы из файла службы подключения и пароля из файла паролей, вы должны указать их в части OPTIONS конфигурации вашей базы данных в DATABASES:
settings.py¶DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"OPTIONS": {
"service": "my_service",
"passfile": ".my_pgpass",
},
}
}
.pg_service.conf¶[my_service]
host=localhost
user=USER
dbname=NAME
port=5432
.my_pgpass¶localhost:5432:NAME:USER:PASSWORD
Серверная часть PostgreSQL передает содержимое OPTIONS в качестве аргументов ключевого слова конструктору соединения, что позволяет более детально контролировать поведение драйвера. Все доступные параметры подробно описаны в документации PostgreSQL.
Предупреждение
Использование имени службы в целях тестирования не поддерживается. Это может быть реализовано позже.
Оптимизация настроек 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:
from django.db.backends.postgresql.psycopg_any import IsolationLevel
DATABASES = {
# ...
"OPTIONS": {
"isolation_level": IsolationLevel.SERIALIZABLE,
},
}
Примечание
На более высоком уровне изоляции транзакций ваше приложение должно быть готовым обрабатывать исключения, которые могут возникнуть при сериализации. Этот параметр предназначен для опытных пользователей.
Роль¶
Если вам нужно использовать для соединений с базой данных роль, отличную от роли, используемой для установления соединения, установите ее в части OPTIONS конфигурации вашей базы данных в DATABASES:
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
# ...
"OPTIONS": {
"assume_role": "my_application_role",
},
},
}
Пул соединений¶
Чтобы использовать пул соединений с psycopg, вы можете либо установить "pool" в части OPTIONS конфигурации вашей базы данных в DATABASES как словарь для передачи в ConnectionPool, либо установить True, чтобы использовать ConnectionPool по умолчанию:
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
# ...
"OPTIONS": {
"pool": True,
},
},
}
Эта опция требует установки psycopg[pool] или psycopg-pool и игнорируется psycopg2.
Привязка параметров на стороне сервера¶
В psycopg 3.1.8+ Django по умолчанию использует курсоры привязки на стороне клиента. Если вы хотите использовать привязку на стороне сервера <psycopg:server-side-binding>`, установите ее в части OPTIONS конфигурации вашей базы данных в DATABASES:
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
# ...
"OPTIONS": {
"server_side_binding": True,
},
},
}
Эта опция игнорируется с помощью psycopg2.
Индексы для колонок 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 для хранения первичных ключей с автоматическим приращением. Столбец идентификаторов заполняется значениями из последовательности, которая отслеживает следующее доступное значение. Присвоение значения автоматически увеличивающемуся полю вручную не приводит к обновлению последовательности поля, что впоследствии может вызвать конфликт. Например:
>>> 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'], чтобы указать template (например, 'template0'), на основе которого будет создана тестовая база данных.
Ускорение выполнения тестов с помощью неустойчивых настроек¶
Вы можете ускорить выполнение тестов, настроив PostgreSQL на кратковременный режим.
Предупреждение
Это опасно: это сделает вашу базу данных более уязвимой к потере или повреждению данных в случае сбоя сервера или отключения питания. Используйте это только на машине разработки, где вы можете легко восстановить все содержимое всех баз данных в кластере.
Общие замечания¶
Django поддерживает MariaDB 10.5 и выше.
Чтобы использовать MariaDB, используйте серверную часть MySQL, которая используется ими совместно. Дополнительные сведения см. в Заметках MySQL.
Заметки MySQL¶
Поддержка версий¶
Django поддерживает MySQL 8.0.11 и выше.
Функция Inspectdb в Django использует базу данных Information_schema, которая содержит подробные данные обо всех схемах базы данных.
Django ожидает, что база данных будет поддерживать Unicode (кодировка UTF-8), и делегирует ей задачу обеспечения транзакций и ссылочной целостности. Важно помнить о том, что два последних параметра фактически не поддерживаются MySQL при использовании механизма хранения MyISAM, см. следующий раздел.
Механизмы хранения¶
MySQL имеет несколько «подсистем хранения». Вы можете изменить механизм хранения по умолчанию в конфигурации сервера.
Механизм хранения MySQL по умолчанию — InnoDB. Этот механизм полностью транзакционен и поддерживает ссылки на внешние ключи. Это рекомендуемый выбор. Однако счетчик автоинкремента InnoDB теряется при перезапуске MySQL, поскольку он не запоминает значение AUTO_INCREMENT, а вместо этого воссоздает его как «max(id)+1». Это может привести к непреднамеренному повторному использованию значений AutoField.
Основные недостатки MyISAM заключаются в том, что он не поддерживает транзакции и не применяет ограничения внешнего ключа.
Драйверы API MySQL БД¶
MySQL имеет пару драйверов, которые реализуют API базы данных Python, описанный в PEP 249:
mysqlclient — это собственный драйвер. Это рекомендуемый выбор.
MySQL Connector/Python — это чистый драйвер Python от Oracle, который не требует клиентской библиотеки MySQL или каких-либо модулей Python за пределами стандартной библиотеки.
Эти драйверы являются потокобезопасными и обеспечивают пул соединений.
В дополнение к драйверу API БД, Django необходим адаптер для доступа к драйверам базы данных из ORM. Django предоставляет адаптер для mysqlclient, а MySQL Connector/Python включает «свой собственный».
mysqlклиент¶
Django требует mysqlclient 1.4.3 или новее.
Коннектор MySQL/Python¶
MySQL Connector/Python доступен на странице загрузки. Адаптер Django доступен в версиях 1.1.X и новее. Он может не поддерживать последние версии Django.
Определения часовых поясов¶
Если вы планируете использовать поддержку часовых поясов 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, сравнения для параметра сортировки 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¶
Значение по умолчанию опции 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. Допустимыми значениями для этой записи являются четыре стандартных уровня изоляции:
'прочитать незафиксированные''прочитать зафиксировано''повторяемое чтение''сериализуемый'
или «Нет», чтобы использовать настроенный уровень изоляции сервера. Однако Django лучше всего работает с фиксированным чтением и по умолчанию использует его, а не повторяемое чтение по умолчанию в MySQL. Возможна потеря данных при повторяемом чтении. В частности, вы можете увидеть случаи, когда 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 <mysql-storage-engines>) поддерживают точки сохранения базы данных <topics-db-transactions-savepoints>`.
Если вы используете механизм хранения MyISAM, имейте в виду, что вы получите ошибки, генерируемые базой данных, если попытаетесь использовать методы API транзакций <topics-db-transactions-savepoints>, связанные с точкой сохранения. Причина этого в том, что обнаружение механизма хранения базы данных/таблицы 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.
Вариант |
МарияДБ |
MySQL |
|---|---|---|
|
Х (≥10,6) |
Х |
|
Х |
Х |
|
Х |
|
|
При использовании 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.31.0 и более поздние версии.
SQLite предоставляет отличную альтернативу разработке для приложений, которые преимущественно доступны только для чтения или требуют меньшего объема установки. Однако, как и в случае со всеми серверами баз данных, существуют некоторые различия, специфичные для SQLite, о которых вам следует знать.
Соответствие подстроки и чувствительность к регистру¶
Для всех версий SQLite наблюдается несколько нелогичное поведение при попытке сопоставления некоторых типов строк. Они срабатывают при использовании фильтров iexact или contains в наборах запросов. Поведение распадается на два случая:
1. For substring matching, all matches are done case-insensitively. That is a
filter such as filter(name__contains="aa") will match a name of "Aabb".
2. For strings containing characters outside the ASCII range, all exact string
matches are performed case-sensitively, even when the case-insensitive options
are passed into the query. So the iexact filter will behave exactly
the same as the exact filter in these cases.
Некоторые возможные обходные пути для этого задокументированы на sqlite.org, но они не используются бэкендом SQLite по умолчанию в Django, поскольку их включение было бы довольно сложно сделать надежным. Таким образом, Django предоставляет поведение SQLite по умолчанию, и вы должны знать об этом при выполнении фильтрации без учета регистра или подстроки.
Десятичная обработка¶
SQLite не имеет настоящего десятичного внутреннего типа. Десятичные значения внутренне преобразуются в тип данных REAL (8-байтовое число с плавающей запятой IEEE), как описано в документации по типам данных SQLite, поэтому они не поддерживают правильно округленную десятичную арифметику с плавающей запятой.
Ошибки «База данных заблокирована»¶
SQLite задуман как облегченная база данных и, следовательно, не может поддерживать высокий уровень параллелизма. Ошибки OperationalError: база данных заблокирована указывают на то, что ваше приложение испытывает больший параллелизм, чем sqlite может обработать в конфигурации по умолчанию. Эта ошибка означает, что один поток или процесс имеет исключительную блокировку соединения с базой данных, а у другого потока истекло время ожидания снятия блокировки.
Оболочка Python SQLite имеет значение тайм-аута по умолчанию, которое определяет, как долго второму потоку разрешено ждать блокировки, прежде чем истечет время ожидания, и выдает ошибку «OperationalError: база данных заблокирована».
Если вы получаете эту ошибку, вы можете решить ее следующим образом:
Переключение на другую базу данных. В определенный момент SQLite становится слишком «облегченным» для реальных приложений, и такого рода ошибки параллелизма указывают на то, что вы достигли этой точки.
Перепишите код, чтобы уменьшить параллелизм и обеспечить кратковременность транзакций базы данных.
Увеличьте значение таймаута по умолчанию, установив параметр базы данных
timeout:"OPTIONS": { # ... "timeout": 20, # ... }
Это заставит SQLite ждать немного дольше, прежде чем выдать ошибку «база данных заблокирована»; на самом деле он ничего не сделает для их решения.
Поведение транзакций¶
SQLite поддерживает три режима транзакций: ОТЛОЖЕННЫЙ, НЕМЕДЛЕННЫЙ и ЭКСКЛЮЗИВНЫЙ.
По умолчанию установлено значение «ОТЛОЖЕНО». Если вам нужно использовать другой режим, установите его в разделе OPTIONS конфигурации вашей базы данных в DATABASES, например:
"OPTIONS": {
# ...
"transaction_mode": "IMMEDIATE",
# ...
}
Чтобы убедиться, что ваши транзакции ждут истечения тайм-аута, прежде чем поднимать сообщение «База данных заблокирована», измените режим транзакции на «НЕМЕДЛЕННО».
Для достижения наилучшей производительности при использовании IMMEDIATE и EXCLUSIVE транзакции должны быть как можно короче. Это может быть сложно гарантировать для всех ваших представлений, поэтому использование ATOMIC_REQUESTS в этом случае не рекомендуется.
Для получения дополнительной информации см. Транзакции в SQLite.
QuerySet.select_for_update() не поддерживается¶
SQLite не поддерживает синтаксис SELECT … FOR UPDATE. Вызов не даст никакого эффекта.
Изоляция при использовании QuerySet.iterator()¶
Существуют особые особенности, описанные в разделе «Изоляция в SQLite» при изменении таблицы во время итерации по ней с использованием QuerySet.iterator(). Если строка добавляется, изменяется или удаляется внутри цикла, то эта строка может появиться, а может и не появиться, или может появиться дважды в последующих результатах, полученных от итератора. Ваш код должен справиться с этим.
Включение расширения JSON1 в SQLite¶
Чтобы использовать JSONField в SQLite, вам необходимо включить расширение JSON1 в библиотеке Python sqlite3. Если расширение не включено в вашей установке, возникнет системная ошибка (fields.E180).
Чтобы включить расширение JSON1, вы можете следовать инструкциям на «вики-странице»_.
Примечание
Расширение JSON1 включено по умолчанию в SQLite 3.38+.
Установка опций прагмы¶
Параметры Pragma`_ можно установить при подключении, используя ``init_command в части OPTIONS конфигурации вашей базы данных в DATABASES. В примере ниже показано, как включить дополнительную надежность синхронной записи и изменить cache_size:
DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
# ...
"OPTIONS": {
"init_command": "PRAGMA synchronous=3; PRAGMA cache_size=2000;",
},
}
}
Примечания Oracle¶
Django поддерживает Oracle Database Server версии 19c и выше. Требуется версия 1.3.2 или выше драйвера Python oracledb.
Не рекомендуется, начиная с версии 5.0: Поддержка cx_Oracle устарела.
Чтобы команда python Manage.py Migrate работала, ваш пользователь базы данных Oracle должен иметь права на выполнение следующих команд:
СОЗДАТЬ ТАБЛИЦУ
СОЗДАТЬ ПОСЛЕДОВАТЕЛЬНОСТЬ
СОЗДАТЬ ПРОЦЕДУРУ
СОЗДАТЬ ТРИГГЕР
Для запуска набора тестов проекта пользователю обычно требуются следующие дополнительные привилегии:
СОЗДАТЬ ПОЛЬЗОВАТЕЛЯ
ИЗМЕНИТЬ ПОЛЬЗОВАТЕЛЯ
УДАЛЕНИЕ ПОЛЬЗОВАТЕЛЯ
СОЗДАТЬ ТАБЛИЧНОЕ ПРОСТРАНСТВО
УДАЛИТЬ ТАБЛИЧНОЕ ПРОСТРАНСТВО
СОЗДАТЬ СЕАНС С ОПЦИЕЙ АДМИНИСТРАТОРА
СОЗДАТЬ ТАБЛИЦУ С ОПЦИЕЙ АДМИНИСТРАТОРА
СОЗДАТЬ ПОСЛЕДОВАТЕЛЬНОСТЬ С ОПЦИЕЙ АДМИНИСТРАТОРА
СОЗДАТЬ ПРОЦЕДУРУ С ОПЦИЕЙ АДМИНИСТРАТОРА
СОЗДАТЬ ТРИГГЕР С ОПЦИЕЙ АДМИНИСТРАТОРА
Хотя роль 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.
Все эти привилегии включены в роль администратора базы данных, которая подходит для использования в базе данных частного разработчика.
Бэкэнд базы данных 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¶
Строку Full 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,
}
Невыполнение этого требования может привести к сбоям и другому странному поведению.
ВСТАВИТЬ… ВОЗВРАЩАЕМСЯ В¶
По умолчанию серверная часть 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, кавычки не имеют никакого эффекта.
При выполнении миграции может возникнуть ошибка ORA-06552, если определенные ключевые слова Oracle используются в качестве имени поля модели или значения опции db_column. Django заключает в кавычки все идентификаторы, используемые в запросах, чтобы предотвратить большинство подобных проблем, но эта ошибка все равно может возникнуть, если в качестве имени столбца используется тип данных Oracle. В частности, старайтесь не использовать имена date, timestamp, number или float в качестве имени поля.
NULL и пустые строки¶
Джанго обычно предпочитает использовать пустую строку (''), а не 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 поставляется со встроенными базами данных. Вы можете создать подкласс существующей серверной части базы данных, чтобы изменить ее поведение, функции или конфигурацию.
Предположим, например, что вам нужно изменить одну функцию базы данных. Во-первых, вам нужно создать новый каталог с базовым модулем. Например:
mysite/
...
mydbengine/
__init__.py
base.py
Модуль base.py должен содержать класс с именем DatabaseWrapper, который является подклассом существующего движка от модуля django.db.backends. Вот пример создания подкласса движка PostgreSQL для изменения класса объектовallows_group_by_selected_pks_on_model:
mysite/mydbengine/base.py¶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, поддерживаемые этими неофициальными серверами, значительно различаются. Запросы относительно конкретных возможностей этих неофициальных серверных частей, а также любые запросы в службу поддержки следует направлять по каналам поддержки, предоставляемым каждым сторонним проектом.