Spec-Zone.ru › Django 2.2

Базы данных

Django официально поддерживает следующие базы данных:

  • PostgreSQL
  • MySQL
  • Oracle
  • SQLite

Также есть ряд баз данных от сторонних разработчиков.

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.4 и выше. Требуется psycopg2 2.5.4 или выше, хотя рекомендуется использовать последнюю версию.

Настройки подключения к 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 (например, hstore, postgis, и т.д.) с помощью миграции, используйте операцию CreateExtension.

Серверные курсоры

При использовании QuerySet.iterator(), Django открывает серверный курсор. По умолчанию PostgreSQL предполагает, что будут извлечены только первые 10% результатов запросов курсора. Планировщик запросов тратит меньше времени на планирование запроса и начинает быстрее возвращать результаты, но это может ухудшить производительность, если извлекается более 10% результатов. Предположения PostgreSQL о количестве строк, извлекаемых для запроса курсора, управляются параметром cursor_tuple_fraction.

Пулы транзакций и серверные курсоры

Использование пула соединений в режиме пула транзакций (например, pgBouncer) требует отключения серверных курсоров для этого подключения.

Серверные курсоры локальны для подключения и остаются открытыми в конце транзакции, когда AUTOCOMMIT равно True. Последующая транзакция может попытаться извлечь больше результатов из серверного курсора. В режиме пула транзакций нет гарантии, что последующие транзакции будут использовать то же соединение. Если используется другое соединение, при попытке ссылки на серверный курсор из транзакции возникает ошибка, потому что доступ к серверным курсорам возможен только в подключении, в котором они были созданы.

Одним из решений является отключение серверных курсоров для подключения в DATABASES путём установки DISABLE_SERVER_SIDE_CURSORS в True.

END_OF_DOCUMENT_MARKER ```

Чтобы воспользоваться курсорами на стороне сервера в режиме объединения транзакций, можно настроить ещё одно подключение к базе данных для выполнения запросов, использующих курсоры на стороне сервера. Это подключение должно быть либо напрямую к базе данных, либо к пулу подключений в режиме пула сессий.

Другой вариант — обернуть каждый 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 для работы в режиме недолговременного хранения.

Предупреждение

Это опасно: это повысит уязвимость вашей базы данных к потере данных или повреждению в случае сбоя сервера или отключения электроэнергии. Используйте только на машине разработчика, где можно легко восстановить все содержимое всех баз данных в кластере.

Примечания по 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 являются отсутствие поддержки транзакций и невыполнение ограничений внешних ключей.

Драйверы API базы данных MySQL

MySQL имеет несколько драйверов, реализующих API баз данных Python, описанный в PEP 249:

  • mysqlclient — это родной драйвер. Он рекомендуется.
  • MySQL Connector/Python — это чистый драйвер Python от Oracle, который не требует библиотеки MySQL или каких-либо модулей Python за пределами стандартной библиотеки.

Эти драйверы потокобезопасны и обеспечивают пулинг подключений.

Помимо драйвера API базы данных, Django нуждается в адаптере для доступа к драйверам баз данных из своего ORM. Django предоставляет адаптер для mysqlclient, а MySQL Connector/Python включает свой.

mysqlclient

Django требует mysqlclient версии 1.3.13 или выше.

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.

Обратите внимание, что в соответствии с Набор символов Unicode MySQL, сравнения для сортировки utf8_general_ci выполняются быстрее, но несколько менее корректно, чем сравнения для utf8_unicode_ci. Если это приемлемо для вашего приложения, используйте utf8_general_ci, так как это быстрее. Если это неприемлемо (например, если вам нужен порядок сортировки по немецкому словарю), используйте utf8_unicode_ci, так как это точнее.

Предупреждение

Формы набора модели проверяют уникальные поля с учётом регистра. Следовательно, при использовании сортировки без учёта регистра набор формы с уникальными значениями поля, отличающимися только регистром, пройдёт валидацию, но при вызове save() будет поднято исключение IntegrityError.

Подключение к базе данных

См. документацию по настройкам.

Параметры подключения используются в следующем порядке:

  1. OPTIONS.
  2. NAME, USER, PASSWORD, HOST, PORT
  3. Файлы опций MySQL.

Другими словами, если вы зададите имя базы данных в 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», а не по умолчанию MySQL — «repeatable read». Потеря данных возможна при использовании «repeatable read». В частности, могут возникнуть ситуации, когда get_or_create() вызовет IntegrityError, но объект не появится в последующем вызове get().

Создание ваших таблиц

При генерации схемы Django не указывает движок хранения, поэтому таблицы будут созданы с тем движком хранения, который настроен по умолчанию на вашем сервере базы данных. Простейший способ — установить нужный движок хранения по умолчанию на вашем сервере базы данных.

Если вы используете хостинг-сервис и не можете изменить движок хранения по умолчанию на вашем сервере, у вас есть несколько вариантов.

  • После создания таблиц выполните оператор ALTER TABLE для преобразования таблицы в новый движок хранения (например, InnoDB):

    ALTER TABLE <tablename> ENGINE=INNODB;
    

    Это может быть утомительно, если у вас много таблиц.

  • Другой вариант — использовать опцию init_command для MySQLdb перед созданием таблиц:

    'OPTIONS': {
       'init_command': 'SET default_storage_engine=INNODB',
    }
    

    Это задаёт движок хранения по умолчанию при подключении к базе данных. После создания ваших таблиц вы должны убрать этот параметр, поскольку он добавляет запрос, необходимый только при создании таблиц, к каждому подключению к базе данных.

Имена таблиц

Существуют известные проблемы даже в последних версиях MySQL, которые могут изменить регистр имени таблицы при выполнении определённых SQL-запросов в определённых условиях. Рекомендуется использовать имена таблиц в нижнем регистре, если это возможно, чтобы избежать проблем, которые могут возникнуть из-за этого поведения. Django использует имена таблиц в нижнем регистре при автоматической генерации имён таблиц из моделей, поэтому это следует учитывать, только если вы переопределяете имя таблицы через параметр db_table.

Точки сохранения

Как Django ORM, так и MySQL (при использовании движка хранения InnoDB хранилища) поддерживают точки сохранения базы данных точек сохранения.

Если вы используете движок хранения MyISAM, имейте в виду, что вы получите ошибки, сгенерированные базой данных, если попытаетесь использовать методы API транзакций, связанные с точками сохранения. Причина в том, что определение движка хранения базы данных/таблицы MySQL является дорогостоящей операцией, поэтому было решено, что динамическое преобразование этих методов в no-op на основе результатов такого определения не стоит затраченных усилий.

Примечания по конкретным полям

Поля символьных данных

Любые поля, хранящиеся с помощью VARCHAR типов столбцов, имеют ограничение max_length до 255 символов, если вы используете unique=True для поля. Это влияет на CharField, SlugField.

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 не поддерживает некоторые опции для оператора SELECT ... FOR UPDATE. Если select_for_update() используется с неподдерживаемой опцией, то возникает NotSupportedError.

Опция MySQL
SKIP LOCKED X (≥8.0.1)
NOWAIT 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 предназначен для использования в качестве лёгкой базы данных, и поэтому не может поддерживать высокий уровень конкурентности. Ошибки «база данных заблокирована» указывают на то, что ваше приложение испытывает более высокую конкурентность, чем 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(). Если строка добавлена, изменена или удалена в цикле, то эта строка может или не может появиться, или может появиться дважды, в последующих результатах, полученных из итератора. Ваш код должен обрабатывать это.

Примечания по Oracle

Django поддерживает Сервер баз данных Oracle версии 12.1 и выше. Требуется версия Python-драйвера cx_Oracle с 6.0 по 7.3.

Для того, чтобы команда 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)))'
),

Параметр threaded

Если вы планируете запустить 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:

  • IBM DB2
  • Microsoft SQL Server
  • Firebird
  • ODBC

Версии Django и возможности ORM, поддерживаемые этими неофициальными бэкендами, значительно различаются. Запросы относительно конкретных возможностей этих неофициальных бэкендов, а также любые запросы по поддержке, следует направлять в каналы поддержки, предоставленные каждым сторонним проектом.

© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/2.2/ref/databases/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API