Базы данных
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.1 и выше. Он требует использования psycopg2 2.4.5 или выше (или 2.5+ если вы хотите использовать django.contrib.postgres).
Настройки соединения PostgreSQL
См. HOST для подробностей.
Оптимизация конфигурации PostgreSQL
Django нуждается в следующих параметрах для соединений с базой данных:
-
client_encoding:'UTF8', -
default_transaction_isolation:'read committed'по умолчанию или значение, заданное в параметрах соединения (см. ниже), -
timezone:'UTC'приUSE_TZравномTrue, значениеTIME_ZONEв противном случае.
Если эти параметры уже имеют правильные значения, 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 для работы без сохранения данных.
Предупреждение
Это опасно: это сделает вашу базу данных более уязвимой к потере данных или повреждению в случае сбоя сервера или отключения питания. Используйте это только на машине разработки, где вы можете легко восстановить все содержимое всех баз данных в кластере.
Примечания к MySQL
Поддержка версий
Django поддерживает MySQL 5.5 и выше.
Функция inspectdb Django использует базу данных information_schema, которая содержит подробные данные обо всех схемах базы данных.
Django ожидает, что база данных поддерживает Unicode (кодировку UTF-8) и делегирует ей задачу по обеспечению транзакций и ссылочной целостности. Важно знать, что оба последних не на самом деле выполняются MySQL при использовании движка хранения MyISAM, см. следующий раздел.
Движки хранения
MySQL имеет несколько движков хранения. Вы можете изменить движок хранения по умолчанию в конфигурации сервера.
До MySQL 5.5.4, движок по умолчанию был MyISAM [1]. Основные недостатки MyISAM заключаются в том, что он не поддерживает транзакции или не проверяет ограничения внешних ключей. С другой стороны, до MySQL 5.6.4 он был единственным движком, поддерживающим полнотекстовый индексирование и поиск.
Начиная с MySQL 5.5.5, движком хранения по умолчанию является InnoDB. Этот движок полностью транзакционный и поддерживает ссылки внешних ключей. Вероятно, это лучший выбор на данный момент. Однако обратите внимание, что счётчик автоматического наращивания InnoDB теряется при перезапуске MySQL, потому что он не запоминает значение AUTO_INCREMENT, а вместо этого пересоздает его как «max(id)+1». Это может привести к непреднамеренному повторному использованию значений AutoField.
Если вы обновляете существующий проект до MySQL 5.5.5 и затем добавляете некоторые таблицы, убедитесь, что ваши таблицы используют один и тот же движок хранения (т.е. MyISAM или InnoDB). В частности, если таблицы, имеющие ForeignKey между ними, используют разные движки хранения, вы можете увидеть ошибку, подобную следующей, при запуске migrate:
_mysql_exceptions.OperationalError: (
1005, "Can't create table '\\db_name\\.#sql-4a8_ab' (errno: 150)"
)
| [1] | Если это не было изменено установщиком вашего пакета MySQL. Например, есть сообщения о том, что установщик Windows Community Server настраивает InnoDB в качестве движка хранения по умолчанию. |
Драйверы MySQL DB API
API Python базы данных описан в PEP 249. MySQL имеет три основных драйвера, которые реализуют этот API:
- MySQLdb — это драйвер по умолчанию, разработанный и поддерживаемый Andy Dustman на протяжении более десяти лет.
-
mysqlclient — это форк
MySQLdb, который поддерживает Python 3 и может использоваться как прямая замена для MySQLdb. На момент написания этой документации, это рекомендуемый выбор для использования MySQL с Django. - MySQL Connector/Python — это чистый драйвер Python от Oracle, который не требует библиотеки MySQL client или каких-либо модулей Python, кроме стандартной библиотеки.
Все эти драйверы являются потокобезопасными и предоставляют кэширование подключений. MySQLdb — единственный, который в настоящее время не поддерживает Python 3.
Помимо драйвера DB API, Django нуждается в адаптере для доступа к драйверам баз данных из своего ORM. Django предоставляет адаптер для MySQLdb/mysqlclient, а MySQL Connector/Python включает собственный.
MySQLdb
Django требует MySQLdb версии 1.2.1p2 или более поздней.
На момент написания этой документации, последняя версия MySQLdb (1.2.5) не поддерживает Python 3. Для использования MySQLdb под Python 3, необходимо установить mysqlclient вместо.
Примечание
Известны проблемы с тем, как MySQLdb преобразует строковые даты в объекты datetime. В частности, строки дат со значением 0000-00-00 являются допустимыми для MySQL, но будут преобразованы в None MySQLdb.
Это означает, что следует проявлять осторожность при использовании loaddata и dumpdata с строками, которые могут содержать 0000-00-00 значения, так как они будут преобразованы в None.
mysqlclient
Django требует mysqlclient версии 1.3.3 или более поздней. Обратите внимание, что Python 3.2 не поддерживается. За исключением поддержки Python 3.3+, mysqlclient должен в основном вести себя так же, как MySQLDB.
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
Параметр сортировки для столбца управляет порядком сортировки данных, а также тем, какие строки сравниваются как равные. Он может быть настроен на уровне базы данных, а также на уровне таблицы и столбца. Это подробно описано в документации MySQL. Во всех случаях вы настраиваете сортировку, напрямую изменяя таблицы базы данных; Django не предоставляет способ настройки этого в определении модели.
По умолчанию, с базой данных UTF-8, MySQL будет использовать сортировку utf8_general_ci. Это приводит к тому, что все сравнения строк на равенство выполняются в регистронезависимом режиме. То есть, "Fred" и "freD" считаются равными на уровне базы данных. Если у вас есть уникальное ограничение на поле, попытка вставки "aa" и "AA" в один и тот же столбец будет недопустимой, так как они сравниваются как равные (и, следовательно, не уникальные) с помощью сортировки по умолчанию.
В большинстве случаев эта настройка не вызовет проблем. Однако, если вам действительно нужны регистрозависимые сравнения для определённого столбца или таблицы, вы должны изменить столбец или таблицу, чтобы использовать сортировку utf8_bin. Самое важное, о чём следует помнить в этом случае, заключается в том, что если вы используете MySQLdb 1.2.2, бэкенд базы данных в Django будет возвращать байтовые строки (вместо строк Unicode) для любых символьных полей, полученных из базы данных. Это существенно отличается от обычной практики Django, которая всегда возвращает строки Unicode. Вам, как разработчику, необходимо учитывать тот факт, что вы будете получать байтовые строки, если вы настроите вашу таблицу(ы) на использование сортировки utf8_bin. Сам Django в большинстве случаев будет работать гладко с такими столбцами (за исключением описанных ниже таблиц contrib.sessions Session и contrib.admin LogEntry), но ваш код должен быть готов к вызову django.utils.encoding.smart_text(), если он действительно хочет работать с согласованными данными — Django этого не сделает за вас (слой бэкенда базы данных и слой заполнения моделей разделены внутри, поэтому слой базы данных не знает, что ему нужно выполнить это преобразование в этом конкретном случае).
Если вы используете MySQLdb 1.2.1p2, стандартный класс Django CharField будет возвращать строки Unicode даже с сортировкой utf8_bin. Однако, поля TextField будут возвращаться как экземпляр array.array (из стандартного модуля Python array). Django не может многого сделать с этим, так как, опять же, информация, необходимая для выполнения необходимых преобразований, недоступна при чтении данных из базы данных. Эта проблема была исправлена в MySQLdb 1.2.2, поэтому, если вы хотите использовать TextField с сортировкой utf8_bin, обновление до версии 1.2.2 и дальнейшая работа с байтовыми строками (что не должно быть слишком сложным), как описано выше, является рекомендуемым решением.
Если вы решите использовать сортировку utf8_bin для некоторых из ваших таблиц с MySQLdb 1.2.1p2 или 1.2.2, вы по-прежнему должны использовать сортировку utf8_general_ci (по умолчанию) для таблицы django.contrib.sessions.models.Session (обычно называемой django_session) и таблицы django.contrib.admin.models.LogEntry (обычно называемой django_admin_log). Это две стандартные таблицы, которые используют TextField внутри.
Обратите внимание, что согласно 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
Несколько других параметров подключения MySQL могут быть полезными, такие как ssl, init_command, и sql_mode. Обратитесь к документации MySQLdb для получения более подробной информации.
Установка sql_mode
Начиная с MySQL 5.7 и при свежих установках MySQL 5.6, значение параметра 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.
Создание ваших таблиц
При генерации схемы 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 и CommaSeparatedIntegerField.
TextField ограничения
MySQL может индексировать только первые N символов BLOB или TEXT столбца. Поскольку TextField не имеет определённой длины, вы не можете пометить его как unique=True. MySQL сообщит: «Столбец BLOB/TEXT ‘<db_column>’ используется в спецификации ключа без длины ключа».
Поддержка дробных секунд для полей Time и DateTime
MySQL 5.6.4 и более поздние версии могут хранить дробные секунды, при условии, что определение столбца включает дробную часть (например, DATETIME(6)). Более ранние версии их вообще не поддерживают. Кроме того, в версиях MySQLdb, более ранних, чем 1.2.5, есть ошибка, которая также препятствует использованию дробных секунд с MySQL.
Django не будет обновлять существующие столбцы для включения дробных секунд, если сервер базы данных их поддерживает. Если вы хотите включить их в существующей базе данных, вам нужно либо вручную обновить столбец в целевой базе данных, выполнив команду типа:
ALTER TABLE `your_table` MODIFY `your_datetime_column` DATETIME(6)
или используя операцию RunSQL в миграции данных.
Ранее Django усекал дробные секунды из datetime и time значений при использовании бэкенда MySQL. Теперь он позволяет базе данных решать, следует ли опускать эту часть значения или нет. По умолчанию новые DateTimeField или TimeField столбцы сейчас создаются с поддержкой дробных секунд в MySQL 5.6.4 или более поздних версиях с mysqlclient или MySQLdb 1.2.5 или более поздних версий.
TIMESTAMP столбцы
Если вы используете устаревшую базу данных, содержащую TIMESTAMP столбцы, необходимо установить USE_TZ = False, чтобы избежать повреждения данных. inspectdb сопоставляет эти столбцы с DateTimeField, и если вы включите поддержку часовых поясов, как MySQL, так и Django попытаются преобразовать значения из UTC в местное время.
Блокировка строк с QuerySet.select_for_update()
MySQL не поддерживает NOWAIT опцию к SELECT ... FOR UPDATE оператору. Если select_for_update() используется с nowait=True, будет возбуждено исключение DatabaseError.
Автоматическое приведение типов может привести к непредсказуемым результатам
При выполнении запроса к строковому типу, но с целочисленным значением, MySQL приведет типы всех значений в таблице к целочисленному типу перед выполнением сравнения. Если ваша таблица содержит значения 'abc', 'def', и вы запрашиваете WHERE mycolumn=0, обе строки будут соответствовать. Аналогично, WHERE mycolumn=1 будет соответствовать значению 'abc1'. Поэтому поля строкового типа, включенные в Django, всегда преобразуют значение в строку перед использованием в запросе.
Если вы реализуете пользовательские поля модели, которые наследуются от Field напрямую, переопределяете get_prep_value() или используете RawSQL, extra() или raw(), вы должны убедиться, что выполняется соответствующее приведение типов.
Примечания к SQLite
SQLite предоставляет отличный вариант для разработки для приложений, которые в основном только для чтения или требуют меньшего объёма установки. Однако, как и на всех серверах баз данных, есть некоторые отличия, специфичные для SQLite, которые следует учитывать.
Сопоставление подстрок и регистронезависимость
Для всех версий SQLite наблюдается несколько неинтуитивное поведение при попытке сопоставить некоторые типы строк. Они возникают при использовании фильтров iexact или contains в наборах запросов. Поведение делится на два случая:
1. Для сопоставления подстрок все соответствия выполняются без учёта регистра. Например, фильтр filter(name__contains="aa") будет соответствовать имени "Aabb".
2. Для строк, содержащих символы за пределами ASCII диапазона, все точные соответствия строк выполняются с учётом регистра, даже когда в запрос передаются опции регистронезависимости. Таким образом, фильтр iexact будет вести себя точно так же, как фильтр exact в этих случаях.
Возможные обходные пути описаны на sqlite.org, но они не используются по умолчанию бэкендом SQLite в Django, так как их включение достаточно сложно сделать надёжно. Поэтому Django предоставляет поведение по умолчанию SQLite, и вы должны учитывать это при выполнении регистронезависимого или подстрочного поиска.
Старый SQLite и CASE выражения
SQLite 3.6.23.1 и более ранние версии содержат ошибку при обработке параметров запроса в CASE выражении, содержащем ELSE и арифметику.
SQLite 3.6.23.1 был выпущен в марте 2010 года, и большинство текущих двоичных дистрибутивов для различных платформ включают более новую версию SQLite, за исключением установщиков Python 2.7 для Windows.
На момент написания этой статьи последняя версия для Windows — Python 2.7.10 — включает SQLite 3.6.21. Вы можете установить pysqlite2 или заменить sqlite3.dll (установленный по умолчанию в C:\Python27\DLLs) на более новую версию с https://www.sqlite.org/, чтобы исправить эту проблему.
Использование новых версий драйвера SQLite DB-API 2.0
Django будет использовать модуль pysqlite2 вместо sqlite3, поставляемого со стандартной библиотекой Python, если найдёт его доступным.
Это позволяет обновлять как интерфейс DB-API 2.0, так и сам SQLite 3 до версий, более новых, чем включённые в вашу конкретную дистрибуцию Python, при необходимости.
“База данных заблокирована” ошибки
SQLite предназначен для использования в качестве лёгкой базы данных, и поэтому не поддерживает высокий уровень конкурентности. Ошибки OperationalError: database is locked указывают на то, что ваше приложение испытывает более высокую конкурентность, чем sqlite может обработать в конфигурации по умолчанию. Эта ошибка означает, что один поток или процесс имеет эксклюзивную блокировку подключения к базе данных, а другой поток превысил время ожидания, ожидая освобождения блокировки.
У Python-обёртки SQLite есть значение таймаута по умолчанию, определяющее, как долго второй поток может ожидать блокировки, прежде чем произойдёт таймаут и будет поднята ошибка OperationalError: database
is locked.
Если у вас возникает эта ошибка, вы можете решить её следующим образом:
- Переключиться на другой бэкенд базы данных. В какой-то момент SQLite становится слишком «лёгким» для реальных приложений, и подобные ошибки конкурентности указывают на то, что вы достигли этой точки.
- Переписать свой код, чтобы уменьшить конкурентность и гарантировать, что транзакции базы данных будут кратковременными.
-
Увеличьте значение таймаута по умолчанию, задав параметр базы данных
timeout:'OPTIONS': { # ... 'timeout': 20, # ... }Это просто заставит SQLite подождать немного дольше, прежде чем сгенерировать ошибки «база данных заблокирована»; это не решит эти ошибки.
QuerySet.select_for_update() не поддерживается
SQLite не поддерживает синтаксис SELECT ... FOR UPDATE. Вызов этой функции не окажет никакого влияния.
Стиль параметра «pyformat» в прямых запросах не поддерживается
Для большинства бэкэндов прямые запросы (Manager.raw() или cursor.execute()) могут использовать стиль параметра «pyformat», где плейсхолдеры в запросе задаются как '%(name)s', а параметры передаются в виде словаря, а не списка. SQLite не поддерживает этот стиль.
Примечания по Oracle
Django поддерживает серверы баз данных Oracle версии 11.2 и выше. Поддерживаются версии Python-драйвера cx_Oracle от 4.3.1 до 5.2.1, хотя рекомендуется использовать версию 5.1.3 или более позднюю, так как эти версии поддерживают Python 3.
Обратите внимание, что из-за ошибки повреждения Unicode в cx_Oracle 5.0, эту версию драйвера не следует использовать с Django; cx_Oracle 5.0.1 устранила эту проблему, поэтому если вы хотите использовать более новую версию cx_Oracle, используйте версию 5.0.1.
cx_Oracle 5.0.1 или выше могут быть скомпилированы с использованием переменной среды WITH_UNICODE. Это рекомендуется, но не является обязательным.
Для того, чтобы команда 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. В частности, это необходимо для собственного набора тестов Django.
До версии Django 1.8 пользователю-тестировщику предоставлялись роли CONNECT и RESOURCE, поэтому дополнительные права, необходимые для выполнения набора тестов, были другими.
Все эти права включены в роль 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 будет использовать другой дескриптор подключения в зависимости от этого выбора.
Многопоточный вариант
Если вы планируете запускать 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, если в качестве имени поля модели или значения параметра db_column используются определённые ключевые слова Oracle. 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:
Поддерживаемые версии Django и функции ORM этих неофициальных бэкэндов значительно различаются. Запросы, касающиеся конкретных возможностей этих неофициальных бэкэндов, а также любые запросы поддержки должны быть направлены в каналы поддержки каждого проекта сторонних разработчиков.
© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/1.9/ref/databases/