• 3.1
  • 5.0
  • 6.1
  • Версия документации: 3.2

Базы данных

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

Существует также ряд бэкэндов баз данных, предоставляемых третьими лицами.

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

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

Общие замечания

Постоянные соединения с базой данных

Persistent connections avoid the overhead of re-establishing a connection to the database in each request. They’re controlled by the CONN_MAX_AGE parameter which defines the maximum lifetime of a connection. It can be set independently for each database.

Значение по умолчанию — «0», сохраняя историческое поведение закрытия соединения с базой данных в конце каждого запроса. Чтобы включить постоянные соединения, установите для CONN_MAX_AGE положительное целое число секунд. Для неограниченных постоянных подключений установите значение «Нет».

Управление соединениями с базой данных

Django выполняет подключение к базе данных при первом запросе. Он держит соединение и использует его для последующих запросов. Django закрывает соединение по истечению CONN_MAX_AGE, или когда оно не может быть больше использовано.

Точнее, Django автоматически создаете соединение с базой данных, если оно необходимо, и нет открытого соединения, потому что это первое соединение, или предыдущее было закрыто.

В начале каждого запроса Django закрывает соединение, если истек его срок. Если ваша база данных закрывает соединение после определенного времени, вам следует указать меньшее значение в CONN_MAX_AGE, чтобы Django не пытался использовать закрытое соединение. (Эта проблема может возникнуть только на сайтах с низким трафиком.)

At the end of each request, Django closes the connection if it has reached its maximum age or if it is in an unrecoverable error state. If any database errors have occurred while processing the requests, Django checks whether the connection still works, and closes it if it doesn’t. Thus, database errors affect at most one request; if the connection becomes unusable, the next request gets a fresh connection.

Предостережения

Так как каждый поток использует отдельное подключение, ваша база данных должна поддерживать необходимое количество соединений.

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

Сервер для разработки создает отдельны поток для каждого запроса, по этому нет смысла использовать постоянные подключения во время разработки.

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

Кодировка

Django предполагает, что все базы данных используют UTF-8. Использование другой кодировки может привести к неожиданному поведению, например ошибке «value too long», в то время, как данные правильны для Django. Смотрите ниже как настраивать различные базы данных.

PostgreSQL

Django supports PostgreSQL 9.6 and higher. psycopg2 2.5.4 or higher is required, though the latest release is recommended.

Настройки подключения PostgreSQL

Смотрите подробности в описании HOST.

Оптимизация настроек PostgreSQL

Django необходимы следующие параметры для подключения:

  • client_encoding: 'UTF8',

  • default_transaction_isolation: 'read committed' по умолчанию, или значение их параметров подключения (смотрите ниже),

  • часовой пояс:
    • когда USE_TZ имеет значение True, 'UTC' по умолчанию или значение TIME_ZONE, установленное для соединения,

    • когда USE_TZ имеет значение False, значение глобальной настройки 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.

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

When using QuerySet.iterator(), Django opens a server-side cursor. By default, PostgreSQL assumes that only the first 10% of the results of cursor queries will be fetched. The query planner spends less time planning the query and starts returning results faster, but this could diminish performance if more than 10% of the results are retrieved. PostgreSQL’s assumptions on the number of rows retrieved for a cursor query is controlled with the cursor_tuple_fraction option.

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

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

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

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

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

Другой вариант — обернуть каждый QuerySet с помощью серверных курсоров в блок atomic(), поскольку он отключает autocommit на время транзакции. Таким образом, курсор на стороне сервера будет существовать только на протяжении транзакции.

Ручное указание значений автоинкрементных первичных ключей

Django uses PostgreSQL’s SERIAL data type to store auto-incrementing primary keys. A SERIAL column is populated with values from a sequence that keeps track of the next available value. Manually assigning a value to an auto-incrementing field doesn’t update the field’s sequence, which might later cause a conflict. For example:

>>> 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.

If you need to specify such values, reset the sequence afterwards to avoid reusing a value that’s already in the table. The sqlsequencereset management command generates the SQL statements to do that.

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

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

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

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

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

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

Общие замечания

Django supports MariaDB 10.2 and higher.

Чтобы использовать MariaDB, используйте серверную часть MySQL, которая используется ими совместно. Дополнительные сведения см. в Заметках MySQL.

Заметки MySQL

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

Django supports MySQL 5.7 and higher.

Функция 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 is a native driver. It’s the recommended choice.

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

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

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

mysqlклиент

Django requires mysqlclient 1.4.0 or later.

Коннектор MySQL/Python

MySQL Connector/Python доступен на странице загрузки. Адаптер Django доступен в версиях 1.1.X и новее. Он может не поддерживать последние версии Django.

Определения часовых поясов

Если вы планируете использовать поддержку часовых поясов Django, используйте mysql_tzinfo_to_sql для загрузки таблиц часовых поясов в базу данных MySQL. Это необходимо сделать только один раз для вашего сервера MySQL, а не для каждой базы данных.

Создание вашей базы данных

You can create your database using the command-line tools and this SQL:

CREATE DATABASE <dbname> CHARACTER SET utf8;

Это гарантирует, что все таблицы и столбцы будут использовать UTF-8 по умолчанию.

Настройки сортировки

Параметр сортировки для столбца определяет порядок сортировки данных, а также то, какие строки сравниваются как равные. Вы можете указать параметр db_collation, чтобы установить имя сортировки столбца для CharField и TextField.

Параметры сортировки также можно настроить на уровне всей базы данных и для каждой таблицы. Это тщательно задокументировано в документации MySQL. В таких случаях необходимо установить параметры сортировки, напрямую манипулируя настройками базы данных или таблицами. Django не предоставляет API для их изменения.

По умолчанию в базе данных UTF-8 MySQL будет использовать параметры сортировки utf8_general_ci. В результате все сравнения строк на равенство выполняются без учета регистра. То есть "Fred" и "freD" считаются равными на уровне базы данных. Если у вас есть ограничение уникальности поля, было бы незаконно пытаться вставить как "aa", так и "AA" в один и тот же столбец, поскольку они сравниваются как равные (и, следовательно, неуникальные) с параметрами сортировки по умолчанию. Если вы хотите проводить сравнения с учетом регистра для определенного столбца или таблицы, измените столбец или таблицу, чтобы использовать параметры сортировки utf8_bin.

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

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

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

Changed in Django 3.2:

Support for setting a database collation for the field was added.

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

Обратитесь к документации по настройкам.

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

  1. ОПЦИИ.

  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

From MySQL 5.7 onwards, the default value of the sql_mode option contains STRICT_TRANS_TABLES. That option escalates warnings into errors when data are truncated upon insertion, so Django highly recommends activating a strict mode for MySQL to prevent data loss (either STRICT_TRANS_TABLES or STRICT_ALL_TABLES).

Если вам нужно настроить режим SQL, вы можете установить переменную sql_mode, как и другие параметры MySQL: либо в файле конфигурации, либо с помощью записи 'init_command': "SET sql_mode='STRICT_TRANS_TABLES'" в части OPTIONS конфигурации вашей базы данных в DATABASES.

Уровень изоляции транзакций

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

  • 'прочитать незафиксированные'

  • 'прочитать зафиксировано'

  • 'повторяемое чтение'

  • 'сериализуемый'

или «Нет», чтобы использовать настроенный уровень изоляции сервера. Однако Django лучше всего работает с фиксированным чтением и по умолчанию использует его, а не повторяемое чтение по умолчанию в MySQL. Возможна потеря данных при повторяемом чтении. В частности, вы можете увидеть случаи, когда get_or_create() вызовет IntegrityError, но объект не появится при последующем вызове get().

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

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

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

  • After the tables are created, execute an ALTER TABLE statement to convert a table to a new storage engine (such as InnoDB):

    ALTER TABLE <tablename> ENGINE=INNODB;
    

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

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

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

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

Название таблицы

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

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

И Django ORM, и MySQL (при использовании механизма хранения InnoDB <mysql-storage-engines>) поддерживают точки сохранения базы данных <topics-db-transactions-savepoints>`.

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

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

Поля символов

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

Ограничения TextField

MySQL может индексировать только первые N символов столбца BLOB или TEXT. Поскольку TextField не имеет определенной длины, вы не можете пометить его как unique=True. MySQL сообщит: «Столбец BLOB/TEXT „<db_column>“ используется в спецификации ключа без длины ключа».

Поддержка дробных секунд для полей Time и DateTime.

MySQL может хранить дробные секунды при условии, что определение столбца включает дробное указание (например, DATETIME(6)).

Django will not upgrade existing columns to include fractional seconds if the database server supports it. If you want to enable them on an existing database, it’s up to you to either manually update the column on the target database, by executing a command like:

ALTER TABLE `your_table` MODIFY `your_datetime_column` DATETIME(6)

или используя операцию RunSQL в переносе данных.

Столбцы TIMESTAMP

Если вы используете устаревшую базу данных, содержащую столбцы TIMESTAMP, вы должны установить USE_TZ = False, чтобы избежать повреждения данных. inspectdb сопоставляет эти столбцы с DateTimeField, и если вы включите поддержку часового пояса, и MySQL, и Django попытаются преобразовать значения из UTC в местное время.

Блокировка строк с помощью QuerySet.select_for_update()

MySQL и MariaDB не поддерживают некоторые параметры оператора SELECT ... FOR UPDATE. Если select_for_update() используется с неподдерживаемой опцией, то выдается ошибка NotSupportedError.

Вариант

МарияДБ

MySQL

ПРОПУСТИТЬ ЗАБЛОКИРОВАН

X (≥8.0.1)

СЕЙЧАС

X (≥10.3)

X (≥8.0.1)

ОФ

X (≥8.0.1)

НЕТ КЛЮЧА

При использовании select_for_update() в MySQL убедитесь, что вы фильтруете набор запросов по крайней мере по набору полей, содержащихся в уникальных ограничениях, или только по полям, охватываемым индексами. В противном случае будет установлена ​​эксклюзивная блокировка записи для всей таблицы на время транзакции.

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

При выполнении запроса к строковому типу, но с целочисленным значением, MySQL приведёт типы всех значений в таблице к целому числу перед выполнением сравнения. Если ваша таблица содержит значения 'abc', 'def' и вы запрашиваете WHERE mycolumn=0, обе строки будут совпадать. Аналогично, WHERE mycolumn=1 будет соответствовать значению abc1. Таким образом, поля строкового типа, включенные в Django, всегда преобразуют значение в строку перед использованием ее в запросе.

Если вы реализуете пользовательские поля модели, которые наследуются от Field напрямую, переопределяют get_prep_value() или используете RawSQL, extra() или raw(), вы должны убедиться, что выполняете соответствующее приведение типов.

SQLite примечания

Django supports SQLite 3.9.0 and later.

SQLite предоставляет отличную альтернативу разработке для приложений, которые преимущественно доступны только для чтения или требуют меньшего объема установки. Однако, как и в случае со всеми серверами баз данных, существуют некоторые различия, специфичные для SQLite, о которых вам следует знать.

Соответствие подстроки и чувствительность к регистру

For all SQLite versions, there is some slightly counter-intuitive behavior when attempting to match some types of strings. These are triggered when using the iexact or contains filters in Querysets. The behavior splits into two cases:

1. For substring matching, all matches are done case-insensitively. That is a filter such as filter(name__contains="aa") will match a name of "Aabb".

2. For strings containing characters outside the ASCII range, all exact string matches are performed case-sensitively, even when the case-insensitive options are passed into the query. So the iexact filter will behave exactly the same as the exact filter in these cases.

Некоторые возможные обходные пути для этого задокументированы на sqlite.org, но они не используются бэкендом SQLite по умолчанию в Django, поскольку их включение было бы довольно сложно сделать надежным. Таким образом, Django предоставляет поведение SQLite по умолчанию, и вы должны знать об этом при выполнении фильтрации без учета регистра или подстроки.

Десятичная обработка

SQLite не имеет настоящего десятичного внутреннего типа. Десятичные значения внутренне преобразуются в тип данных REAL (8-байтовое число с плавающей запятой IEEE), как описано в документации по типам данных SQLite, поэтому они не поддерживают правильно округленную десятичную арифметику с плавающей запятой.

Ошибки «База данных заблокирована»

SQLite задуман как облегченная база данных и, следовательно, не может поддерживать высокий уровень параллелизма. Ошибки OperationalError: база данных заблокирована указывают на то, что ваше приложение испытывает больший параллелизм, чем sqlite может обработать в конфигурации по умолчанию. Эта ошибка означает, что один поток или процесс имеет исключительную блокировку соединения с базой данных, а у другого потока истекло время ожидания снятия блокировки.

Оболочка Python SQLite имеет значение тайм-аута по умолчанию, которое определяет, как долго второму потоку разрешено ждать блокировки, прежде чем истечет время ожидания, и выдает ошибку «OperationalError: база данных заблокирована».

Если вы получаете эту ошибку, вы можете решить ее следующим образом:

  • Переключение на другую базу данных. В определенный момент SQLite становится слишком «облегченным» для реальных приложений, и такого рода ошибки параллелизма указывают на то, что вы достигли этой точки.

  • Перепишите код, чтобы уменьшить параллелизм и обеспечить кратковременность транзакций базы данных.

  • Увеличьте значение таймаута по умолчанию, установив параметр базы данных timeout:

    'OPTIONS': {
        # ...
        'timeout': 20,
        # ...
    }
    

    Это заставит SQLite ждать немного дольше, прежде чем выдать ошибку «база данных заблокирована»; на самом деле он ничего не сделает для их решения.

QuerySet.select_for_update() не поддерживается

SQLite не поддерживает синтаксис SELECT … FOR UPDATE. Вызов не даст никакого эффекта.

«pyformat» parameter style in raw queries not supported

For most backends, raw queries (Manager.raw() or cursor.execute()) can use the «pyformat» parameter style, where placeholders in the query are given as '%(name)s' and the parameters are passed as a dictionary rather than a list. SQLite does not support this.

Изоляция при использовании QuerySet.iterator()

Существуют особые особенности, описанные в разделе «Изоляция в SQLite» при изменении таблицы во время итерации по ней с использованием QuerySet.iterator(). Если строка добавляется, изменяется или удаляется внутри цикла, то эта строка может появиться, а может и не появиться, или может появиться дважды в последующих результатах, полученных от итератора. Ваш код должен справиться с этим.

Включение расширения JSON1 в SQLite

Чтобы использовать JSONField в SQLite, вам необходимо включить расширение JSON1 в библиотеке Python sqlite3. Если расширение не включено в вашей установке, возникнет системная ошибка (fields.E180).

Чтобы включить расширение JSON1, вы можете следовать инструкциям на «вики-странице»_.

Примечания Oracle

Django supports Oracle Database Server versions 12.2 and higher. Version 6.0 or higher of the cx_Oracle Python driver is required.

Чтобы команда python Manage.py Migrate работала, ваш пользователь базы данных Oracle должен иметь права на выполнение следующих команд:

  • СОЗДАТЬ ТАБЛИЦУ

  • СОЗДАТЬ ПОСЛЕДОВАТЕЛЬНОСТЬ

  • СОЗДАТЬ ПРОЦЕДУРУ

  • СОЗДАТЬ ТРИГГЕР

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

  • СОЗДАТЬ ПОЛЬЗОВАТЕЛЯ

  • ИЗМЕНИТЬ ПОЛЬЗОВАТЕЛЯ

  • УДАЛЕНИЕ ПОЛЬЗОВАТЕЛЯ

  • СОЗДАТЬ ТАБЛИЧНОЕ ПРОСТРАНСТВО

  • УДАЛИТЬ ТАБЛИЧНОЕ ПРОСТРАНСТВО

  • СОЗДАТЬ СЕАНС ​​С ОПЦИЕЙ АДМИНИСТРАТОРА

  • СОЗДАТЬ ТАБЛИЦУ С ОПЦИЕЙ АДМИНИСТРАТОРА

  • СОЗДАТЬ ПОСЛЕДОВАТЕЛЬНОСТЬ С ОПЦИЕЙ АДМИНИСТРАТОРА

  • СОЗДАТЬ ПРОЦЕДУРУ С ОПЦИЕЙ АДМИНИСТРАТОРА

  • СОЗДАТЬ ТРИГГЕР С ОПЦИЕЙ АДМИНИСТРАТОРА

Хотя роль RESOURCE имеет необходимые привилегии CREATE TABLE, CREATE SEQUENCE, CREATE PROCEDURE и CREATE TRIGGER, а пользователь, получивший RESOURCE With ADMIN OPTION, может предоставить RESOURCE, такой пользователь не может предоставить отдельные привилегии (например, CREATE TABLE), и таким образом RESOURCE With ADMIN OPTION обычно недостаточно для запуска тестов.

Некоторые наборы тестов также создают представления или материализованные представления; для их запуска пользователю также необходимы привилегии «CREATE VIEW With ADMIN OPTION» и «CREATE MATERIALIZED VIEW With ADMIN OPTION». В частности, это необходимо для собственного набора тестов Django.

Все эти привилегии включены в роль администратора базы данных, которая подходит для использования в базе данных частного разработчика.

Бэкэнд базы данных Oracle использует пакеты SYS.DBMS_LOB и SYS.DBMS_RANDOM, поэтому вашему пользователю потребуются разрешения на его выполнение. Обычно по умолчанию он доступен всем пользователям, но если это не так, вам необходимо предоставить разрешения следующим образом:

GRANT EXECUTE ON SYS.DBMS_LOB TO user;
GRANT EXECUTE ON SYS.DBMS_RANDOM TO user;

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

Чтобы подключиться с использованием имени службы вашей базы данных Oracle, ваш файл settings.py должен выглядеть примерно так:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.oracle',
        'NAME': 'xe',
        'USER': 'a_user',
        'PASSWORD': 'a_password',
        'HOST': '',
        'PORT': '',
    }
}

В этом случае вам следует оставить HOST и PORT пустыми. Однако, если вы не используете файл tnsnames.ora или аналогичный метод именования и хотите подключиться с использованием SID («xe» в этом примере), тогда заполните оба HOST и PORT следующим образом:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.oracle',
        'NAME': 'xe',
        'USER': 'a_user',
        'PASSWORD': 'a_password',
        'HOST': 'dbprod01ned.mycompany.com',
        'PORT': '1540',
    }
}

Вам следует либо указать оба HOST и PORT, либо оставить оба пустыми строками. Django будет использовать другой дескриптор подключения в зависимости от этого выбора.

Полный DSN и Easy Connect

Строку Full DSN или Easy Connect можно использовать в NAME, если оба HOST и PORT пусты. Этот формат необходим, например, при использовании RAC или подключаемых баз данных без tnsnames.ora.

Пример строки Easy Connect:

'NAME': 'localhost:1521/orclpdb1',

Пример полной строки DSN:

'NAME': (
    '(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521))'
    '(CONNECT_DATA=(SERVICE_NAME=orclpdb1)))'
),

Резьбовой вариант

Если вы планируете запускать Django в многопоточной среде (например, Apache, используя модуль MPM по умолчанию в любой современной операционной системе), то вы должны установить для параметра threaded конфигурации вашей базы данных Oracle значение True:

'OPTIONS': {
    'threaded': True,
},

Невыполнение этого требования может привести к сбоям и другому странному поведению.

ВСТАВИТЬ… ВОЗВРАЩАЕМСЯ В

По умолчанию серверная часть Oracle использует предложение RETURNING INTO для эффективного получения значения AutoField при вставке новых строк. Такое поведение может привести к ошибке DatabaseError в некоторых необычных настройках, например, при вставке в удаленную таблицу или в представление с триггером INSTEAD OF. Предложение RETURNING INTO можно отключить, установив для параметра use_returning_into конфигурации базы данных значение False:

'OPTIONS': {
    'use_returning_into': False,
},

В этом случае серверная часть Oracle будет использовать отдельный запрос SELECT для получения значений AutoField.

Проблемы с именованием

Oracle накладывает ограничение на длину имени в 30 символов. Чтобы учесть это, серверная часть усекает идентификаторы базы данных, чтобы они соответствовали размеру, заменяя последние четыре символа усеченного имени повторяемым значением хеш-функции MD5. Кроме того, серверная часть преобразует идентификаторы базы данных в верхний регистр.

Чтобы предотвратить эти преобразования (обычно это требуется только при работе с устаревшими базами данных или доступом к таблицам, принадлежащим другим пользователям), используйте имя в кавычках в качестве значения для db_table:

class LegacyModel(models.Model):
    class Meta:
        db_table = '"name_left_in_lowercase"'

class ForeignModel(models.Model):
    class Meta:
        db_table = '"OTHER_USER"."NAME_ONLY_SEEMS_OVER_30"'

Имена в кавычках также можно использовать с другими поддерживаемыми Django базами данных; однако, за исключением Oracle, кавычки не имеют никакого эффекта.

При выполнении миграции может возникнуть ошибка ORA-06552, если определенные ключевые слова Oracle используются в качестве имени поля модели или значения опции db_column. Django заключает в кавычки все идентификаторы, используемые в запросах, чтобы предотвратить большинство подобных проблем, но эта ошибка все равно может возникнуть, если в качестве имени столбца используется тип данных Oracle. В частности, старайтесь не использовать имена date, timestamp, number или float в качестве имени поля.

NULL и пустые строки

Джанго обычно предпочитает использовать пустую строку (''), а не NULL, но Oracle обрабатывает обе строки одинаково. Чтобы обойти эту проблему, серверная часть Oracle игнорирует явную опцию null для полей, которые имеют пустую строку в качестве возможного значения, и генерирует DDL, как если бы null=True. При выборке из базы данных предполагается, что значение NULL в одном из этих полей действительно означает пустую строку, и данные автоматически преобразуются, чтобы отразить это предположение.

Ограничения TextField

Бэкэнд Oracle хранит TextFields как столбцы NCLOB. Oracle в целом накладывает некоторые ограничения на использование таких столбцов LOB:

  • Столбцы LOB нельзя использовать в качестве первичных ключей.

  • Столбцы LOB нельзя использовать в индексах.

  • Столбцы LOB нельзя использовать в списке SELECT DISTINCT. Это означает, что попытка использовать метод QuerySet.distinct в модели, которая включает столбцы TextField, приведет к ошибке ORA-00932 при запуске в Oracle. В качестве обходного пути используйте метод QuerySet.defer в сочетании с distinct(), чтобы предотвратить включение столбцов TextField в список SELECT DISTINCT.

Создание подклассов встроенных серверных баз данных

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

Consider, for example, that you need to change a single database feature. First, you have to create a new directory with a base module in it. For example:

mysite/
    ...
    mydbengine/
        __init__.py
        base.py

Модуль base.py должен содержать класс с именем DatabaseWrapper, который является подклассом существующего движка от модуля django.db.backends. Вот пример создания подкласса движка PostgreSQL для изменения класса объектовallows_group_by_selected_pks_on_model:

mysite/mydbengine/base.py
from django.db.backends.postgresql import base, features

class DatabaseFeatures(features.DatabaseFeatures):
    def allows_group_by_selected_pks_on_model(self, model):
        return True

class DatabaseWrapper(base.DatabaseWrapper):
    features_class = DatabaseFeatures

Наконец, вы должны указать DATABASE-ENGINE в вашем файле settings.py:

DATABASES = {
    'default': {
        'ENGINE': 'mydbengine',
        ...
    },
}

Текущий список механизмов баз данных можно просмотреть, заглянув в django/db/backends.

Использование сторонней базы данных

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

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

Back to Top