Базы данных

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

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

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

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

Общие примечания

Постоянные соединения

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

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

Управление подключением

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

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

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

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

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

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

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

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

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

Кодировка

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

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

Django поддерживает PostgreSQL 9.6 и выше. Требуется psycopg2 2.5.4 или выше, но рекомендуется последняя версия.

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

См. HOSTПодробности.

Оптимизация конфигурации PostgreSQL

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

  • client_encoding: 'UTF8',
  • default_transaction_isolation: по умолчанию или значение, заданное в параметрах подключения (см. ниже),'read committed'
  • timezone:
    • когда USE_TZесть True, 'UTC'по умолчанию, или TIME_ZONEзначение , установленное для подключения,
    • когда USE_TZесть False, значение глобальной TIME_ZONEнастройки.

Если эти параметры уже имеют правильные значения, Django не будет устанавливать их для каждого нового соединения, что немного улучшает производительность. Вы можете настроить их непосредственно в postgresql.confбазе данных или более удобно для каждого пользователя базы данных с помощью ALTER ROLE .

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

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

Как и сам PostgreSQL, Django по умолчанию использует уровень изоляции . Если вам нужен более высокий уровень изоляции, такой как или , установите его в части конфигурации вашей базы данных в :READ COMMITTED REPEATABLE READSERIALIZABLEOPTIONSDATABASES

import psycopg2.extensions

DATABASES = {
    # ...
    'OPTIONS': {
        'isolation_level': psycopg2.extensions.ISOLATION_LEVEL_SERIALIZABLE,
    },
}

Примечание

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

Индексы varcharи textстолбцов

При указании db_index=Trueполей модели Django обычно выводит один оператор. Однако, если тип базы данных для поля либо или (например, используется , и ), тем Джанго создаст дополнительный индекс , который использует соответствующий класс оператора PostgreSQL для столбца. Дополнительный индекс необходим для правильного выполнения поиска с использованием оператора в своем SQL, как это делается с типами поиска и .CREATE INDEXvarchartextCharFieldFileFieldTextFieldLIKEcontainsstartswith

Операция миграции для добавления расширений

Если вам нужно добавить расширение PostgreSQL (например hstore, postgisи т. Д.) С помощью миграции, используйте CreateExtensionоперацию.

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

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

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

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

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

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

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

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

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

Django использует тип данных PostgreSQL SERIAL для хранения автоматически увеличивающихся первичных ключей. SERIALСтолбец заполняется значениями из последовательности , которая отслеживает следующей доступной стоимости. Присвоение значения автоматически увеличивающемуся полю вручную не обновляет последовательность полей, что впоследствии может вызвать конфликт. Например:

>>> from django.contrib.auth.models import User
>>> User.objects.create(username='alice', pk=1)
<User: alice>
>>> # The sequence hasn't been updated; its next value is 1.
>>> User.objects.create(username='bob')
...
IntegrityError: duplicate key value violates unique constraint
"auth_user_pkey" DETAIL:  Key (id)=(1) already exists.

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

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

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

Ускорение выполнения теста с недолговечными настройками

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

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

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

Заметки MariaDB

Django поддерживает MariaDB 10.2 и выше.

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

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

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

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

inspectdbФункция Django использует information_schemaбазу данных, которая содержит подробные данные обо всех схемах базы данных.

Django ожидает, что база данных будет поддерживать Unicode (кодировка UTF-8), и делегирует ей задачу обеспечения транзакций и ссылочной целостности. Важно помнить о том, что два последних на самом деле не применяются MySQL при использовании механизма хранения MyISAM, см. Следующий раздел.

Механизмы хранения

MySQL имеет несколько механизмов хранения . Вы можете изменить механизм хранения по умолчанию в конфигурации сервера.

Механизм хранения MySQL по умолчанию - InnoDB . Этот механизм полностью транзакционный и поддерживает ссылки на внешние ключи. Это рекомендуемый выбор. Однако счетчик автоинкремента InnoDB теряется при перезапуске MySQL, потому что он не запоминает AUTO_INCREMENTзначение, вместо этого воссоздает его как «max (id) +1». Это может привести к непреднамеренному повторному использованию AutoField значений.

Основные недостатки MyISAM заключаются в том, что он не поддерживает транзакции и не применяет ограничения внешнего ключа.

Драйверы MySQL DB API

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

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

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

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

mysqlclient

Django требует mysqlclient 1.4.0 или новее.

Коннектор MySQL / 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.

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

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

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

По умолчанию в базе данных 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 потому что это более точно.

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

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

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

Добавлена ​​поддержка настройки параметров сортировки базы данных для поля.

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

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

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

  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, значение 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'"OPTIONSDATABASES

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

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

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

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

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

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

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

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

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

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

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

Любые поля, которые хранятся с 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 не обновит существующие столбцы, чтобы включить дробные секунды, если сервер базы данных поддерживает это. Если вы хотите включить их в существующей базе данных, вам нужно либо вручную обновить столбец в целевой базе данных, выполнив такую ​​команду, как:

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

или с помощью RunSQLоперации переноса данных .

TIMESTAMPстолбцы

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

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

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

Вариант MariaDB MySQL
SKIP LOCKED   Х (≥8.0.1)
NOWAIT Х (≥10,3) Х (≥8.0.1)
OF   Х (≥8.0.1)
NO KEY    

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

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

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

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

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

Django поддерживает SQLite 3.9.0 и новее.

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

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

Для всех версий SQLite наблюдается некоторое противоречивое поведение при попытке сопоставления некоторых типов строк. Они запускаются при использовании фильтров iexactили containsв наборах запросов. Поведение делится на два случая:

1. Для сопоставления подстрок все совпадения выполняются без учета регистра. Это фильтр, который filter(name__contains="aa")будет соответствовать имени "Aabb".

2. Для строк, содержащих символы вне диапазона ASCII, все точные совпадения строк выполняются с учетом регистра, даже если в запрос передаются параметры без учета регистра. Таким образом, в этих случаях iexactфильтр будет вести себя точно так же, как и exactфильтр.

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

Обработка десятичных чисел

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

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

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

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

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

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

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

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

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

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

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

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

Стиль параметра «pyformat» в необработанных запросах не поддерживается

Для большинства бэкэндов необработанные запросы ( Manager.raw()или cursor.execute()) могут использовать стиль параметра «pyformat», где заполнители в запросе задаются как, '%(name)s'а параметры передаются как словарь, а не список. SQLite не поддерживает это.

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

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

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

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

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

Заметки Oracle

Django поддерживает Oracle Database Server версии 12.2 и выше. Требуется версия 6.0 или выше драйвера cx_Oracle Python.

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

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

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

  • СОЗДАТЬ ПОЛЬЗОВАТЕЛЯ
  • ИЗМЕНИТЬ ПОЛЬЗОВАТЕЛЯ
  • УДАЛИТЬ ПОЛЬЗОВАТЕЛЯ
  • СОЗДАТЬ ТАБЛИЧНОЕ ПРОСТРАНСТВО
  • DROP TABLESPACE
  • СОЗДАТЬ СЕССИЮ С ОПЦИЕЙ АДМИНИСТРАТОРА
  • СОЗДАТЬ ТАБЛИЦУ С ОПЦИЕЙ АДМИНИСТРАТОРА
  • СОЗДАТЬ ПОСЛЕДОВАТЕЛЬНОСТЬ С ОПЦИЕЙ АДМИНИСТРАТОРА
  • СОЗДАТЬ ПРОЦЕДУРУ С ОПЦИЕЙ АДМИНИСТРАТОРА
  • СОЗДАТЬ ТРИГГЕР С ОПЦИЕЙ АДМИНИСТРАТОРА

В то время как RESOURCEроль искомые , , и привилегия, и пользователь предоставил может предоставить , например, пользователь не может предоставить индивидуальные привилегии (например ), и , таким образом , как правило , не достаточно для выполнения тестов.CREATE TABLECREATE SEQUENCECREATE PROCEDURECREATE TRIGGERRESOURCE WITH ADMIN OPTIONRESOURCECREATE TABLERESOURCE WITH ADMIN OPTION

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

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

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

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

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

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

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

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

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

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

Полный DSN и Easy Connect

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

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

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

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

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

Вариант с резьбой

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

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

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

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

По умолчанию серверная часть Oracle использует предложение для эффективного извлечения значения при вставке новых строк. Такое поведение может привести к некоторым необычным настройкам, например, при вставке в удаленную таблицу или в представление с триггером. Предложение можно отключить, установив для параметра конфигурации базы данных значение :RETURNING INTOAutoFieldDatabaseErrorINSTEAD OFRETURNING INTOuse_returning_intoFalse

'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 в целом:

  • Столбцы больших объектов нельзя использовать в качестве первичных ключей.
  • Столбцы больших объектов нельзя использовать в индексах.
  • Столбцы больших объектов нельзя использовать в списке. Это означает, что попытка использовать метод в модели, которая включает столбцы, приведет к ошибке при запуске с Oracle. В качестве обходного пути используйте этот метод вместе с, чтобы предотвратить включение столбцов в список.SELECT DISTINCTQuerySet.distinctTextFieldORA-00932QuerySet.deferdistinct()TextFieldSELECT DISTINCT

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

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

Представьте, например, что вам нужно изменить одну функцию базы данных. Во-первых, вам нужно создать новый каталог с baseмодулем в нем. Например:

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

Copyright ©2021 All rights reserved