Spec-Zone.ru › Django 2.0

Базы данных

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.3 и выше. Требуется 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.

Курсоры на стороне сервера

Новое в Django 1.11.

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

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

Новое в Django 1.11.1.

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

Шаблоны тестовых баз данных

Новое в Django 1.11.

Вы можете использовать настройку TEST['TEMPLATE'] для указания шаблона (например, 'template0') для создания тестовой базы данных.

Ускорение выполнения тестов с помощью настроек недолговечных данных

Вы можете ускорить время выполнения тестов, настроив PostgreSQL на недолговечные данные.

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

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

Примечания к MySQL

Поддержка версий

Django поддерживает MySQL 5.5 и выше.

Функция Django inspectdb использует базу данных 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

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.3.7 по 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.

Обратите внимание, что согласно MySQL Unicode Character Sets, сравнения для сортировки 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.

Уровень изоляции

Новое в Django 1.11.

При выполнении одновременных нагрузок транзакции базы данных из разных сеансов (скажем, отдельных потоков, обрабатывающих различные запросы) могут взаимодействовать друг с другом. Эти взаимодействия влияют на уровень изоляции транзакции каждого сеанса. уровень изоляции транзакции. Вы можете установить уровень изоляции соединения с помощью записи 'isolation_level' в части OPTIONS вашей конфигурации базы данных в DATABASES. Допустимые значения для этой записи — четыре стандартных уровня изоляции:

  • 'read uncommitted'
  • 'read committed'
  • 'repeatable read'
  • 'serializable'

или None, чтобы использовать уровень изоляции, настроенный на сервере. Однако Django лучше всего работает с уровнем изоляции read committed, а не с по умолчанию в MySQL, repeatable read. При использовании repeatable read возмоны потери данных.

Изменено в Django 2.0:

В более старых версиях бэкенд базы данных MySQL по умолчанию использует уровень изоляции базы данных (который по умолчанию равен repeatable read), а не read committed.

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

При генерации 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.

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 не поддерживает параметры NOWAIT, SKIP LOCKED, и OF оператора SELECT ... FOR UPDATE. Если select_for_update() используется с nowait=True, skip_locked=True, или of, то возбуждается NotSupportedError.

Автоматическое приведение типов может привести к неожиданным результатам

При выполнении запроса к строковому типу, но с целым значением, 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 предназначен для работы с лёгкими базами данных и поэтому не может поддерживать высокий уровень одновременности. Ошибки OperationalError: database is locked указывают на то, что ваше приложение испытывает более высокую одновременность, чем sqlite может обработать в стандартной конфигурации. Эта ошибка означает, что один поток или процесс имеет эксклюзивную блокировку соединения с базой данных, а другой поток истек, ожидая освобождения блокировки.

У оболочки SQLite для Python есть значение таймаута по умолчанию, определяющее, как долго второй поток может ожидать блокировки, прежде чем таймаут истечёт и будет вызвана ошибка 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 12.1 и выше. Поддерживаются версии Python-драйвера cx_Oracle с 5.2 по 6.4.1.

Для работы команды 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.

Все эти привилегии включены в роль 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, если определённые ключевые слова 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:

  • SAP SQL Anywhere
  • 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.0/ref/databases/

Spec-Zone.ru

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