Базы данных
Django официально поддерживает следующие базы данных:
Также существует ряд бэкендов баз данных, предоставляемых третьими сторонами.
Django пытается поддерживать как можно больше функций на всех бэкендах баз данных. Однако не все бэкенды баз данных одинаковы, и нам пришлось принять решения по проектированию, какие функции поддерживать и какие предположения можно безопасно сделать.
В этом файле описаны некоторые из функций, которые могут быть важны для использования Django. Он не предназначен для замены документации или справочных руководств, специфичных для сервера.
Общие замечания
Постоянные подключения
Постоянные подключения позволяют избежать накладных расходов на повторное установление соединения с базой данных в каждом запросе. Они контролируются параметром CONN_MAX_AGE, который определяет максимальный срок жизни соединения. Его можно установить независимо для каждой базы данных.
Значение по умолчанию равно 0, сохраняя историческое поведение закрытия подключения к базе данных в конце каждого запроса. Для включения постоянных подключений установите CONN_MAX_AGE на положительное целое число секунд. Для неограниченных постоянных подключений установите его в None.
Управление подключениями
Django открывает подключение к базе данных при первом выполнении запроса к базе данных. Оно сохраняет это подключение открытым и повторно использует его в последующих запросах. Django закрывает подключение, когда оно превышает максимальный срок, определенный параметром CONN_MAX_AGE, или когда оно больше не применимо.
Подробно, Django автоматически открывает подключение к базе данных всякий раз, когда ему нужно и когда у него его нет — либо потому, что это первое подключение, либо потому, что предыдущее подключение было закрыто.
В начале каждого запроса Django закрывает подключение, если оно достигло максимального возраста. Если ваша база данных закрывает бездействующие подключения после некоторого времени, вы должны установить CONN_MAX_AGE на меньшее значение, чтобы Django не пытался использовать подключение, которое было закрыто сервером базы данных. (Эта проблема может затрагивать только сайты с очень низким трафиком.)
В конце каждого запроса Django закрывает подключение, если оно достигло максимального возраста или находится в состоянии необратимой ошибки. Если при обработке запросов произошли какие-либо ошибки базы данных, Django проверяет, работает ли подключение, и закрывает его, если нет. Таким образом, ошибки базы данных влияют максимум на один запрос; если подключение становится непригодным, следующий запрос получает новое подключение.
Ограничения
Поскольку каждый поток поддерживает собственное подключение, ваша база данных должна поддерживать как минимум столько одновременных подключений, сколько у вас есть потоков-работников.
Иногда к базе данных не будет обращаться большинство ваших представлений, например, потому что это база данных внешней системы или благодаря кэшированию. В таких случаях вы должны установить CONN_MAX_AGE на низкое значение или даже на 0, потому что нет смысла поддерживать подключение, которое, скорее всего, не будет повторно использовано. Это поможет сохранить небольшое количество одновременных подключений к этой базе данных.
Сервер разработки создает новый поток для каждого обрабатываемого запроса, что сводит на нет эффект постоянных подключений. Не включайте их во время разработки.
Когда Django устанавливает подключение к базе данных, оно настраивает соответствующие параметры в зависимости от используемого бэкенда. Если вы включаете постоянные подключения, эта настройка больше не повторяется в каждом запросе. Если вы изменяете параметры, такие как уровень изоляции подключения или часовой пояс, вы должны либо восстановить значения по умолчанию Django в конце каждого запроса, либо принудительно установить соответствующее значение в начале каждого запроса, либо отключить постоянные подключения.
Кодировка
Django предполагает, что все базы данных используют кодировку UTF-8. Использование других кодировок может привести к неожиданному поведению, например, к ошибкам «значение слишком длинное» от вашей базы данных для данных, которые допустимы в Django. См. Примечания к конкретным базам данных ниже, чтобы узнать, как правильно настроить вашу базу данных.
Примечания к PostgreSQL
Django поддерживает PostgreSQL 9.5 и выше. Требуется psycopg2 2.5.4 или выше, хотя рекомендуется использовать последнюю версию.
Настройки подключения к PostgreSQL
См. HOST для получения подробной информации.
Оптимизация конфигурации PostgreSQL
Django нуждается в следующих параметрах для своих подключений к базе данных:
-
client_encoding:'UTF8', -
default_transaction_isolation:'read committed'по умолчанию или значение, установленное в параметрах подключения (см. ниже),
Если эти параметры уже имеют правильные значения, Django не будет устанавливать их для каждого нового подключения, что немного улучшает производительность. Вы можете настроить их непосредственно в postgresql.conf или более удобно для каждого пользователя базы данных с помощью ALTER ROLE.
Django будет работать без этой оптимизации, но каждое новое подключение будет выполнять дополнительные запросы для установки этих параметров.
Уровень изоляции базы данных
Как и сам PostgreSQL, Django по умолчанию использует уровень изоляции READ COMMITTED уровень изоляции. Если вам нужен более высокий уровень изоляции, например, REPEATABLE READ или SERIALIZABLE, установите его в части OPTIONS конфигурации вашей базы данных в DATABASES:
import psycopg2.extensions
DATABASES = {
# ...
'OPTIONS': {
'isolation_level': psycopg2.extensions.ISOLATION_LEVEL_SERIALIZABLE,
},
}
Примечание
При более высоких уровнях изоляции ваше приложение должно быть готово обрабатывать исключения, возникающие при сбоях сериализации. Этот параметр предназначен для использования в продвинутых сценариях.
Индексы для столбцов varchar и text
При указании db_index=True на полях вашей модели Django обычно выводит одну CREATE INDEX инструкцию. Однако, если тип базы данных для поля — varchar или text (например, используемые CharField, FileField, и TextField), Django создаст дополнительный индекс, который использует соответствующий класс оператора PostgreSQL для столбца. Дополнительный индекс необходим для правильной обработки запросов, которые используют оператор LIKE в своем SQL, как это делается с типами поиска contains и startswith.
Операция миграции для добавления расширений
Если вам нужно добавить расширение PostgreSQL (например, hstore, postgis, и т.д.) с помощью миграции, используйте операцию CreateExtension.
Курсоры на стороне сервера 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.6 и выше.
Функция 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.
Определения часовых поясов
Если вы планируете использовать поддержку часовых поясов Django поддержки часовых поясов, используйте mysql_tzinfo_to_sql для загрузки таблиц часовых поясов в базу данных MySQL. Это необходимо сделать только один раз для вашего сервера MySQL, а не для каждой базы данных.
Создание вашей базы данных
Вы можете создать свою базу данных с помощью командной строки и этого SQL:
CREATE DATABASE <dbname> CHARACTER SET utf8;
Это гарантирует, что все таблицы и столбцы по умолчанию будут использовать UTF-8.
Настройки сортировки
Настройка сортировки столбца управляет порядком сортировки данных и тем, какие строки сравниваются как равные. Она может быть установлена на уровне всей базы данных, а также на уровне таблицы и столбца. Это подробно описано в документации MySQL. В любом случае, вы устанавливаете сортировку путём непосредственного изменения таблиц базы данных; Django не предоставляет способ установить это в определении модели.
По умолчанию в базе данных UTF-8 MySQL будет использовать сортировку utf8_general_ci. Это приводит к тому, что все сравнения строк на равенство выполняются в регистронезависимом режиме. То есть, "Fred" и "freD" считаются равными на уровне базы данных. Если у вас есть ограничение уникальности на поле, попытка вставить как "aa" , так и "AA" в один и тот же столбец будет незаконной, так как они сравниваются как равные (и, следовательно, не уникальные) с сортировкой по умолчанию. Если вам нужно чувствительное к регистру сравнение для определённого столбца или таблицы, измените столбец или таблицу на использование сортировки utf8_bin.
Обратите внимание, что согласно MySQL Unicode Character Sets, сравнения для сортировки utf8_general_ci выполняются быстрее, но немного менее корректно, чем сравнения для utf8_unicode_ci. Если это приемлемо для вашего приложения, вы должны использовать utf8_general_ci, так как оно быстрее. Если это неприемлемо (например, если вам требуется немецкий лексикографический порядок), используйте utf8_unicode_ci, так как оно точнее.
Предупреждение
Формы множественных форм модели проверяют уникальные поля в регистрозависимом режиме. Таким образом, при использовании регистронезависимой сортировки форма множественных форм с уникальными значениями поля, отличающимися только регистром, пройдёт проверку, но при вызове save(), будет возбуждено IntegrityError.
Подключение к базе данных
Обратитесь к документации по настройкам.
Настройки подключения используются в таком порядке:
Другими словами, если вы установите имя базы данных в OPTIONS, это будет иметь приоритет над NAME, которое, в свою очередь, переопределит всё, что есть в файле параметров MySQL.
Вот пример конфигурации, которая использует файл параметров MySQL:
# settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'OPTIONS': {
'read_default_file': '/path/to/my.cnf',
},
}
}
# my.cnf
[client]
database = NAME
user = USER
password = PASSWORD
default-character-set = utf8
Несколько других параметров подключения MySQLdb могут оказаться полезными, такими как ssl, init_command, и sql_mode.
Установка sql_mode
От MySQL 5.7 и далее, а также при свежих установках 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.
Уровень изоляции
При выполнении одновременных нагрузок транзакции базы данных из разных сессий (скажем, отдельных потоков, обрабатывающих разные запросы) могут взаимодействовать друг с другом. Эти взаимодействия зависят от уровня изоляции транзакции каждой сессии. Уровень изоляции транзакции можно установить для соединения с помощью записи 'isolation_level' в части OPTIONS конфигурации вашей базы данных в DATABASES. Допустимые значения для этой записи — четыре стандартных уровня изоляции:
'read uncommitted''read committed''repeatable read''serializable'
или None, чтобы использовать уровень изоляции, настроенный на сервере. Однако Django лучше всего работает с и по умолчанию использует уровень «read committed», а не «repeatable read», который является по умолчанию в MySQL. Потеря данных возможна при использовании уровня «repeatable read». В частности, вы можете столкнуться с ситуациями, когда get_or_create() вызовет ошибку IntegrityError, но объект не появится в последующем вызове get().
Создание ваших таблиц
При генерации схемы Django не указывает движок хранения, поэтому таблицы будут созданы с движком хранения по умолчанию, который настроен на вашем сервере базы данных. Проще всего установить для вашего сервера базы данных движок хранения по умолчанию, который вам нужен.
Если вы используете хостинг-сервис и не можете изменить движок хранения по умолчанию на сервере, у вас есть несколько вариантов.
-
После создания таблиц выполните оператор
ALTER TABLEдля преобразования таблицы в новый движок хранения (например, InnoDB):ALTER TABLE <tablename> ENGINE=INNODB;
Это может быть утомительно, если у вас много таблиц.
-
Другой вариант — использовать параметр
init_commandдля MySQLdb перед созданием ваших таблиц:'OPTIONS': { 'init_command': 'SET default_storage_engine=INNODB', }Это устанавливает движок хранения по умолчанию при подключении к базе данных. После того, как ваши таблицы были созданы, вам следует удалить этот параметр, поскольку он добавляет запрос, необходимый только при создании таблиц, к каждому подключению к базе данных.
Имена таблиц
В даже последних версиях MySQL есть известные проблемы, которые могут привести к изменению регистра имени таблицы при выполнении определенных операторов SQL в определенных условиях. Рекомендуется использовать имена таблиц в нижнем регистре, если это возможно, чтобы избежать проблем, которые могут возникнуть из-за этого поведения. Django использует имена таблиц в нижнем регистре, когда автоматически генерирует имена таблиц из моделей, поэтому это в основном нужно учитывать, если вы переопределяете имя таблицы с помощью параметра db_table.
Сохраняемые точки
Как ORM Django, так и MySQL (при использовании движка хранения InnoDB движка хранения) поддерживают сохраняемые точки базы данных. Сохраняемые точки.
Если вы используете движок хранения MyISAM, имейте в виду, что при попытке использовать методы API транзакций, связанные с сохраняемыми точками вы получите ошибки, генерируемые базой данных. Причина в том, что определение движка хранения базы данных/таблицы MySQL является дорогостоящей операцией, поэтому было решено, что это не стоит того, чтобы динамически преобразовывать эти методы в no-op на основе результатов такого определения.
Примечания по конкретным полям
Поля символьных данных
Для полей, хранящихся с VARCHAR типами столбцов, max_length может быть ограничено 255 символами, если вы используете unique=True для поля. Это влияет на CharField, SlugField. Подробнее см. документацию MySQL.
TextField ограничения
MySQL может индексировать только первые N символов столбца типа BLOB или TEXT. Поскольку TextField не имеет определенной длины, вы не можете отметить его как unique=True. MySQL сообщит: «Столбец BLOB/TEXT ‘<db_column>’ используется в спецификации ключа без длины ключа».
Поддержка дробных секунд для полей типа Time и DateTime
MySQL 5.6.4 и более поздние версии могут хранить дробные секунды, при условии, что определение столбца включает указание дробной части (например, DATETIME(6)). Более ранние версии их вообще не поддерживают.
Django не будет обновлять существующие столбцы для включения дробных секунд, если сервер базы данных их поддерживает. Если вы хотите включить их в существующую базу данных, вам нужно либо вручную обновить столбец в целевой базе данных, выполнив команду типа:
ALTER TABLE `your_table` MODIFY `your_datetime_column` DATETIME(6)
или используя операцию RunSQL в миграции данных.
TIMESTAMP столбцы
Если вы используете устаревшую базу данных, содержащую TIMESTAMP столбцы, вы должны установить USE_TZ = False, чтобы избежать повреждения данных. inspectdb сопоставляет эти столбцы с DateTimeField, и если вы включите поддержку часовых поясов, как MySQL, так и Django будут пытаться преобразовать значения из UTC в местное время.
Блокировка строк с QuerySet.select_for_update()
MySQL и MariaDB не поддерживают некоторые варианты оператора SELECT ... FOR UPDATE. Если select_for_update() используется с неподдерживаемым параметром, то возникает NotSupportedError.
| Параметр | MariaDB | MySQL |
|---|---|---|
SKIP LOCKED | X (≥8.0.1) | |
NOWAIT | X (≥10.3) | X (≥8.0.1) |
OF |
При использовании 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.8.3 и более поздние версии.
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-обёртке для 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 не поддерживает это.
Изоляция при использовании QuerySet.iterator()
Существуют особые соображения, описанные в Изоляция в SQLite, при модификации таблицы во время итерации по ней с помощью QuerySet.iterator(). Если строка добавляется, изменяется или удаляется внутри цикла, то эта строка может или не может отображаться, или может отображаться дважды в последующих результатах, полученных из итератора. Ваш код должен обрабатывать это.
Включение расширения JSON1 в SQLite
Для использования JSONField в SQLite, необходимо включить расширение JSON1 в библиотеке Python sqlite3. Если расширение не включено в вашей установке, произойдёт системная ошибка (fields.E180).
Чтобы включить расширение JSON1, следуйте инструкциям на странице вики.
Примечания по Oracle
Django поддерживает сервер базы данных Oracle версий 12.2 и выше. Требуется версия Python-драйвера cx_Oracle 6.0 или выше.
Для работы команды python manage.py migrate у пользователя вашей базы данных Oracle должны быть права на выполнение следующих команд:
- CREATE TABLE
- CREATE SEQUENCE
- CREATE PROCEDURE
- CREATE TRIGGER
Для выполнения набора тестов проекта пользователю обычно требуются дополнительные права:
- CREATE USER
- ALTER USER
- DROP USER
- CREATE TABLESPACE
- DROP TABLESPACE
- CREATE SESSION WITH ADMIN OPTION
- CREATE TABLE WITH ADMIN OPTION
- CREATE SEQUENCE WITH ADMIN OPTION
- CREATE PROCEDURE WITH ADMIN OPTION
- CREATE TRIGGER WITH ADMIN OPTION
Хотя роль RESOURCE имеет необходимые права CREATE TABLE, CREATE SEQUENCE, CREATE PROCEDURE, и CREATE TRIGGER, и пользователь, которому предоставлены права RESOURCE WITH ADMIN OPTION может предоставлять права RESOURCE, такой пользователь не может предоставлять отдельные привилегии (например, CREATE TABLE), и поэтому RESOURCE WITH ADMIN OPTION обычно недостаточно для выполнения тестов.
Некоторые наборы тестов также создают представления или материализованные представления; для их выполнения пользователю также нужны права CREATE VIEW WITH ADMIN OPTION и CREATE MATERIALIZED VIEW WITH ADMIN OPTION. В частности, это необходимо для собственного набора тестов Django.
Все эти права включены в роль DBA, которая подходит для использования на частной базе данных разработчика.
Бэкэнд базы данных Oracle использует пакеты SYS.DBMS_LOB и SYS.DBMS_RANDOM, поэтому пользователю потребуется разрешение на выполнение этих пакетов. Как правило, доступ к ним предоставляется по умолчанию всем пользователям, но если это не так, вам нужно предоставить разрешения следующим образом:
GRANT EXECUTE ON SYS.DBMS_LOB TO user; GRANT EXECUTE ON SYS.DBMS_RANDOM TO user;
Подключение к базе данных
Для подключения с использованием имени службы вашей базы данных Oracle, ваш файл settings.py должен выглядеть примерно так:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.oracle',
'NAME': 'xe',
'USER': 'a_user',
'PASSWORD': 'a_password',
'HOST': '',
'PORT': '',
}
}
В этом случае вы должны оставить оба поля HOST и PORT пустыми. Однако, если вы не используете файл tnsnames.ora или аналогичный метод именования и хотите подключиться через SID («xe» в данном примере), тогда заполните оба поля HOST и PORT следующим образом:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.oracle',
'NAME': 'xe',
'USER': 'a_user',
'PASSWORD': 'a_password',
'HOST': 'dbprod01ned.mycompany.com',
'PORT': '1540',
}
}
Вы должны либо указать оба поля HOST и PORT, либо оставить их пустыми. Django будет использовать другой дескриптор подключения в зависимости от этого выбора.
Полный DSN и Easy Connect
Строка 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,
},
Отсутствие этого параметра может привести к авариям и другим нестандартным ошибкам.
INSERT … RETURNING INTO
По умолчанию бэкэнд Oracle использует ключевое слово RETURNING INTO для эффективного получения значения поля AutoField при добавлении новых строк. Это поведение может привести к ошибке DatabaseError в некоторых нестандартных конфигурациях, например, при добавлении в удалённую таблицу или в представление с триггером INSTEAD OF. Ключевое слово RETURNING INTO можно отключить, установив параметр use_returning_into конфигурации базы данных на значение False:
'OPTIONS': {
'use_returning_into': False,
},
В этом случае бэкэнд Oracle будет использовать отдельный запрос SELECT для получения значений AutoField.
Проблемы с именами
Oracle накладывает ограничение на длину имени в 30 символов. Для этого бэкэнд обрезает идентификаторы базы данных до соответствия, заменяя последние четыре символа обрезанного имени повторяющимся значением хеша MD5. Кроме того, бэкэнд преобразует идентификаторы базы данных в верхний регистр.
Чтобы предотвратить эти преобразования (это обычно требуется только при работе со старыми базами данных или при доступе к таблицам, принадлежащим другим пользователям), используйте имя в кавычках в качестве значения для db_table:
class LegacyModel(models.Model):
class Meta:
db_table = '"name_left_in_lowercase"'
class ForeignModel(models.Model):
class Meta:
db_table = '"OTHER_USER"."NAME_ONLY_SEEMS_OVER_30"'
Имена в кавычках также можно использовать с другими поддерживаемыми бэкендами баз данных Django; за исключением Oracle, однако, кавычки не влияют на результат.
При выполнении migrate, может возникнуть ошибка ORA-06552, если определённые ключевые слова Oracle используются в качестве имени поля модели или значения опции db_column. Django приводит все идентификаторы, используемые в запросах, к каноническому виду, чтобы предотвратить большинство подобных проблем, но эта ошибка всё же может произойти при использовании типа данных Oracle в качестве имени столбца. В частности, следует избегать использования имён date, timestamp, number или float в качестве имени поля.
NULL и пустые строки
Django обычно предпочитает использовать пустую строку ('') вместо NULL, но Oracle обрабатывает оба значения одинаково. Для решения этой проблемы бэкэнд Oracle игнорирует явную опцию null для полей, которые могут содержать пустую строку в качестве значения, и генерирует DDL так, как будто null=True. При извлечении данных из базы данных предполагается, что значение NULL в одном из этих полей на самом деле означает пустую строку, и данные автоматически преобразуются в соответствии с этим предположением.
TextField ограничения
Бэкэнд Oracle хранит TextFields в виде столбцов типа NCLOB. Oracle накладывает некоторые ограничения на использование таких столбцов LOB в целом:
- Столбцы LOB не могут использоваться в качестве первичных ключей.
- Столбцы LOB не могут использоваться в индексах.
- Столбцы LOB не могут использоваться в списке
SELECT DISTINCT. Это означает, что попытка использовать методQuerySet.distinctдля модели, которая включает столбцыTextField, приведёт к ошибкеORA-00932при выполнении запроса в Oracle. В качестве обходного решения используйте методQuerySet.deferв сочетании сdistinct(), чтобы предотвратить включение столбцовTextFieldв списокSELECT DISTINCT.
Наследование встроенных бэкэндов баз данных
Django поставляется со встроенными бэкендами баз данных. Вы можете унаследовать существующий бэкэнд базы данных, чтобы изменить его поведение, функции или конфигурацию.
Предположим, вам необходимо изменить одну функцию базы данных. Сначала нужно создать новую директорию с модулем base в ней. Например:
mysite/
...
mydbengine/
__init__.py
base.py
Модуль base.py должен содержать класс с именем DatabaseWrapper, который наследуется от существующего движка из модуля django.db.backends. Вот пример наследования движка PostgreSQL для изменения класса функции allows_group_by_selected_pks_on_model.
from django.db.backends.postgresql import base, features
class DatabaseFeatures(features.DatabaseFeatures):
def allows_group_by_selected_pks_on_model(self, model):
return True
class DatabaseWrapper(base.DatabaseWrapper):
features_class = DatabaseFeatures
Наконец, вы должны указать DATABASE-ENGINE в вашем файле settings.py:
DATABASES = {
'default': {
'ENGINE': 'mydbengine',
...
},
}
Текущий список движков баз данных можно посмотреть в django/db/backends.
Использование бэкэнда базы данных сторонних разработчиков
Помимо официально поддерживаемых баз данных, существуют бэкэнды сторонних разработчиков, которые позволяют использовать другие базы данных с Django:
Поддерживаемые версии Django и возможности ORM этих неофициальных бэкэндов значительно различаются. Вопросы о конкретных возможностях этих неофициальных бэкэндов, а также любые запросы поддержки следует направлять в каналы поддержки каждого проекта сторонних разработчиков.
© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/3.1/ref/databases/