Django正式支持以下数据库:
还有一些 database backends provided by third parties .
Django尝试在所有数据库后端支持尽可能多的功能。然而,并非所有的数据库后端都是相同的,我们必须对哪些特性需要支持以及哪些假设可以安全地进行设计决策。
这个文件描述了一些可能与Django使用相关的特性。它不打算取代服务器特定的文档或参考手册。
持久连接避免了在每个HTTP请求中重新建立到数据库的连接的开销。它们是由 CONN_MAX_AGE
参数,该参数定义连接的最长生存期。它可以为每个数据库单独设置。
默认值为 0
,保留在每个请求结束时关闭数据库连接的历史行为。要启用永久连接,请设置 CONN_MAX_AGE
秒的正整数。对于无限制的持久连接,将其设置为 None
.
Django在首次进行数据库查询时打开与数据库的连接。它使这个连接保持打开状态,并在随后的请求中重用它。当连接超过 CONN_MAX_AGE
或者当它不再可用时。
详细地说,Django在需要数据库连接时自动打开到数据库的连接,但它还没有连接,这可能是因为这是第一个连接,也可能是因为前一个连接已关闭。
在每个请求的开始,Django会关闭连接(如果连接已达到其最大期限)。如果数据库在一段时间后终止空闲连接,则应设置 CONN_MAX_AGE
以使django不尝试使用已被数据库服务器终止的连接。(此问题可能只影响非常低的流量站点。)
在每个请求结束时,如果连接已达到其最大寿命或处于不可恢复的错误状态,Django将关闭连接。如果在处理请求时发生任何数据库错误,Django将检查连接是否仍在工作,如果连接不工作,则将其关闭。因此,数据库错误最多影响每个应用程序的工作线程一个请求;如果连接变得不可用,则下一个请求将获得新的连接。
设置 CONN_HEALTH_CHECKS
至 True
可用于提高连接重用的健壮性,并在数据库服务器关闭连接时防止错误,数据库服务器现在已准备好接受和服务新连接,例如在数据库服务器重新启动之后。每个请求仅执行一次运行状况检查,并且仅当在处理请求期间访问数据库时执行。
因为每个线程都维护自己的连接,所以您的数据库必须至少支持与工作线程相同数量的同时连接。
有时大多数视图都无法访问数据库,例如,因为它是外部系统的数据库,或者由于缓存。在这种情况下,你应该 CONN_MAX_AGE
低值,甚至 0
,因为维护不太可能重用的连接是没有意义的。这将有助于保持与此数据库的同时连接数较少。
开发服务器为它处理的每个请求创建一个新线程,从而消除持久连接的影响。在开发过程中不要启用它们。
当Django建立到数据库的连接时,它会根据所使用的后端设置适当的参数。如果启用持久连接,则不再重复每个请求。如果修改连接的隔离级别或时区等参数,则应在每个请求结束时恢复django的默认值,在每个请求开始时强制使用适当的值,或者禁用持久连接。
如果在Django的请求-响应周期之外的长期运行流程中创建连接,则该连接将保持打开状态,直到显式关闭或发生超时。
Django假设所有数据库都使用UTF-8编码。使用其他编码可能会导致意外行为,例如数据库中有效数据的“值太长”错误。有关如何正确设置数据库的信息,请参阅下面特定于数据库的说明。
Django支持PostgreSQL 13及更高版本。 psycopg 3.1.8+或 psycopg2 需要2.8.4以上版本,但最新版本 psycopg 建议使用3.1.8+。
备注
支持 psycopg2
很可能会在将来的某个时候被弃用和移除。
见 HOST
有关详细信息。
若要使用来自 connection service file 和来自 password file ,则必须在 OPTIONS
中的数据库配置的一部分 DATABASES
:
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"OPTIONS": {
"service": "my_service",
"passfile": ".my_pgpass",
},
}
}
[my_service]
host=localhost
user=USER
dbname=NAME
port=5432
localhost:5432:NAME:USER:PASSWORD
PostgreSQL后端将 OPTIONS
作为连接构造函数的关键字参数,允许对驱动程序行为进行更高级的控制。全部可用 parameters 在PostgreSQL文档中进行了详细描述。
警告
不支持将服务名称用于测试目的。这 may be implemented later 。
Django的数据库连接需要以下参数:
client_encoding
: 'UTF8'
,
default_transaction_isolation
: 'read committed'
默认情况下,或在连接选项中设置的值(见下文)。
如果这些参数已经有了正确的值,Django不会为每个新连接设置它们,这会稍微提高性能。您可以直接在中配置它们 postgresql.conf
或更方便每个数据库用户使用 ALTER ROLE .
没有这种优化,Django就可以正常工作,但是每个新连接都会执行一些额外的查询来设置这些参数。
就像PostgreSQL本身一样,Django默认为 READ COMMITTED
isolation level . 如果您需要更高的隔离级别,例如 REPEATABLE READ
或 SERIALIZABLE
把它设置在 OPTIONS
数据库配置的一部分 DATABASES
::
from django.db.backends.postgresql.psycopg_any import IsolationLevel
DATABASES = {
# ...
"OPTIONS": {
"isolation_level": IsolationLevel.SERIALIZABLE,
},
}
备注
在较高的隔离级别下,应用程序应该准备好处理在序列化失败时引发的异常。此选项设计用于高级用途。
如果需要为数据库连接使用与用于建立连接的角色不同的角色,请在 OPTIONS
中的数据库配置的一部分 DATABASES
**
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
# ...
"OPTIONS": {
"assume_role": "my_application_role",
},
},
}
使用 psycopg 3.1.8+,Django默认为 client-side binding cursors 。如果要使用 server-side binding 将其设置在 OPTIONS
中的数据库配置的一部分 DATABASES
**
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
# ...
"OPTIONS": {
"server_side_binding": True,
},
},
}
使用时将忽略此选项 psycopg2
。
varchar
和 text
柱¶指定时 db_index=True
在模型字段上,Django通常输出一个 CREATE INDEX
语句。但是,如果字段的数据库类型为 varchar
或 text
(例如,由 CharField
, FileField
和 TextField
,然后django将创建一个使用适当的 PostgreSQL operator class 对于列。额外的索引对于正确执行使用 LIKE
其SQL中的运算符,与 contains
和 startswith
查找类型。
如果需要添加PostgreSQL扩展(如 hstore
, postgis
等)使用迁移,使用 CreateExtension
操作。
使用时 QuerySet.iterator()
,Django打开了一个 server-side cursor 。默认情况下,PostgreSQL假定只提取游标查询结果的前10%。查询规划器计划查询所花费的时间更少,并开始更快地返回结果,但如果检索到超过10%的结果,则可能会降低性能。PostgreSQL对游标查询检索的行数的假设由 cursor_tuple_fraction 选择。
在事务池模式下使用连接池(例如 PgBouncer )需要为该连接禁用服务器端游标。
服务器端游标是连接的本地游标,当 AUTOCOMMIT
是 True
. 后续事务可能会尝试从服务器端光标获取更多结果。在事务池模式下,不能保证后续事务将使用相同的连接。如果使用不同的连接,则在事务引用服务器端光标时会引发错误,因为服务器端光标只能在创建它们的连接中访问。
一种解决方案是在 DATABASES
通过设置 DISABLE_SERVER_SIDE_CURSORS
到 True
.
为了从事务池模式的服务器端游标中获益,可以设置 another connection to the database 以便执行使用服务器端游标的查询。在会话池模式下,此连接需要直接连接到数据库或连接池。
另一种选择是包装每一个 QuerySet
在 atomic()
阻止,因为它禁用 autocommit
在交易期间。这样,服务器端光标将只在事务期间活动。
Django使用PostgreSQL的标识列来存储自动递增的主键。标识列中的值填充 sequence 它跟踪下一个可用值。手动为自动递增的字段赋值不会更新该字段的顺序,这可能会在以后导致冲突。例如:
>>> 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']
设置以指定 template (例如) 'template0'
)从中创建测试数据库。
您可以通过 configuring PostgreSQL to be non-durable .
警告
这很危险:在服务器崩溃或断电的情况下,它会使数据库更容易受到数据丢失或损坏的影响。只在开发机器上使用它,在那里您可以轻松地恢复集群中所有数据库的全部内容。
Django支持MariaDB 10.5及更高版本。
要使用MariaDB,请使用MySQL后端,这是两者共享的。见 MySQL notes 了解更多详细信息。
Django支持MySQL 8.0.11及更高版本。
Django inspectdb
功能使用 information_schema
数据库,其中包含所有数据库架构的详细数据。
Django希望数据库支持Unicode(UTF-8编码),并将强制执行事务和引用完整性的任务委托给它。在使用myisam存储引擎时,必须意识到后两个引擎实际上不是由mysql强制执行的,请参见下一节。
MySQL有几个 storage engines . 可以在服务器配置中更改默认存储引擎。
MySQL的默认存储引擎是 InnoDB. 此引擎是完全事务性的,支持外键引用。这是推荐的选择。但是,innodb autoincrement计数器在MySQL重新启动时丢失,因为它不记得 AUTO_INCREMENT
值,而不是将其重新创建为“max(id)+1”。这可能会导致 AutoField
价值观。
主要缺点是 MyISAM 它不支持事务或强制使用外键约束。
MySQL有两个驱动程序来实现中描述的python数据库API。 PEP 249 :
mysqlclient 是一名本地司机。它是 the recommended choice 。
MySQL Connector/Python 是来自Oracle的纯python驱动程序,它不需要mysql客户机库或标准库之外的任何python模块。
这些驱动程序是线程安全的,并提供连接池。
除了DBAPI驱动程序之外,Django还需要一个适配器来从其ORM访问数据库驱动程序。Django为mysqlclient提供了一个适配器,而mysql connector/python包括 its own .
姜戈要求 mysqlclient 1.4.3或更高版本。
mysql connector/python可从 download page . Django适配器在1.1.x及更高版本中提供。它可能不支持Django的最新版本。
如果你打算用 Django 的 timezone support 使用 mysql_tzinfo_to_sql 将时区表加载到MySQL数据库中。这只需要为您的MySQL服务器完成一次,而不是每个数据库。
你可以的 create your database 使用命令行工具和以下SQL:
CREATE DATABASE <dbname> CHARACTER SET utf8;
这样可以确保所有表和列在默认情况下都使用UTF-8。
列的排序规则设置控制数据的排序顺序以及哪些字符串比较为相等。您可以指定 db_collation
参数设置列的排序规则名称 CharField
和 TextField
.
排序规则也可以在数据库范围内的每个表上设置。这是 documented thoroughly 在MySQL文档中。在这种情况下,必须通过直接操作数据库设置或表来设置排序规则。Django不提供API来更改它们。
默认情况下,对于utf-8数据库,mysql将使用 utf8_general_ci
校对。这将导致在 case-insensitive 态度。也就是说, "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
将被提升。
连接设置的使用顺序如下:
换句话说,如果在 OPTIONS
,这将优先于 NAME
,它将覆盖 MySQL option file .
下面是一个使用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 connection options 可能有用,例如 ssl
, init_command
和 sql_mode
.
sql_mode
¶的缺省值 sql_mode
选项包含 STRICT_TRANS_TABLES
。当数据在插入时被截断时,该选项会将警告升级为错误,因此Django强烈建议激活 strict mode 对于MySQL,为了防止数据丢失( STRICT_TRANS_TABLES
或 STRICT_ALL_TABLES
)。
如果需要自定义SQL模式,可以设置 sql_mode
变量和其他MySQL选项一样:要么在配置文件中,要么在条目中 'init_command': "SET sql_mode='STRICT_TRANS_TABLES'"
在 OPTIONS
数据库配置的一部分 DATABASES
.
在运行并发加载时,来自不同会话(例如,处理不同请求的独立线程)的数据库事务可能会相互交互。这些交互受每个会话的影响 transaction isolation level . 可以使用 'isolation_level'
进入 OPTIONS
数据库配置的一部分 DATABASES
. 此项的有效值是四个标准隔离级别:
'read uncommitted'
'read committed'
'repeatable read'
'serializable'
或 None
使用服务器配置的隔离级别。但是,django最适合并默认为read committed,而不是mysql的默认可重复读取。通过可重复读取可能会丢失数据。特别是,您可能会看到 get_or_create()
将提高 IntegrityError
但是这个物体不会出现在后面 get()
打电话。
当Django生成模式时,它没有指定存储引擎,因此将使用数据库服务器配置的默认存储引擎创建表。最简单的解决方案是将数据库服务器的默认存储引擎设置为所需的引擎。
如果您使用的是托管服务,并且无法更改服务器的默认存储引擎,那么您有几个选项。
在创建表之后,执行 ALTER TABLE
将表转换为新存储引擎(如InnoDB)的语句:
ALTER TABLE <tablename> ENGINE=INNODB;
如果你有很多表格,这会很乏味。
另一种选择是使用 init_command
创建表之前mysqldb的选项:
"OPTIONS": {
"init_command": "SET default_storage_engine=INNODB",
}
这将在连接到数据库时设置默认的存储引擎。创建表后,应删除此选项,因为它将只在表创建期间需要的查询添加到每个数据库连接中。
有 known issues 甚至在MySQL的最新版本中,当某些SQL语句在某些条件下执行时,也可能导致表名的情况发生更改。建议您尽可能使用小写表名,以避免此行为可能引起的任何问题。Django在从模型自动生成表名时使用小写表名,因此,如果要通过 db_table
参数。
django orm和mysql(使用innodb时 storage engine )支持数据库 savepoints .
如果使用myisam存储引擎,请注意,如果尝试使用 savepoint-related methods of the transactions API . 原因是,检测MySQL数据库/表的存储引擎是一项昂贵的操作,因此,根据检测结果,在no op中动态转换这些方法是不值得的。
与一起存储的任何字段 VARCHAR
列类型可能具有 max_length
如果正在使用,则限制为255个字符 unique=True
为了田野。这种影响 CharField
, SlugField
. 见 the MySQL documentation 了解更多详细信息。
TextField
局限性¶MySQL只能索引 BLOB
或 TEXT
列。自从 TextField
没有定义的长度,不能将其标记为 unique=True
. MySQL将报告:“在没有密钥长度的密钥规范中使用了blob/text列'<db_column>”。
MySQL可以存储小数秒,前提是列定义中包含一个小数表示(例如。 DATETIME(6)
)
如果数据库服务器支持,Django将不会升级现有列以包含小数秒。如果要在现有数据库上启用它们,则由您决定是否手动更新目标数据库上的列,方法是执行如下命令:
ALTER TABLE `your_table` MODIFY `your_datetime_column` DATETIME(6)
或使用 RunSQL
A中的操作 data migration .
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(≥10.6) |
X |
|
X |
X |
|
X |
|
|
使用时 select_for_update()
在MySQL上,请确保至少根据Unique约束中包含的一组字段或仅根据索引覆盖的字段来筛选查询集。否则,将在事务持续时间内获取整个表上的独占写锁。
当对字符串类型执行查询时,但使用整数值时,MySQL将强制表中所有值的类型为整数,然后再执行比较。如果表中包含值 'abc'
, 'def'
然后你查询 WHERE mycolumn=0
,两行都匹配。同样地, WHERE mycolumn=1
将匹配值 'abc1'
. 因此,django中包含的字符串类型字段在查询中使用该值之前,将始终将该值强制转换为字符串。
如果实现从继承的自定义模型字段 Field
直接,是压倒性的 get_prep_value()
或使用 RawSQL
, extra()
或 raw()
,您应该确保执行适当的类型转换。
Django支持SQLite 3.27.0及更高版本。
SQLite 为主要是只读的或需要更小的安装占用空间的应用程序提供了一个极好的开发替代方案。但是,与所有数据库服务器一样,您应该注意到特定于sqlite的一些差异。
对于所有的sqlite版本,在尝试匹配某些类型的字符串时,都有一些稍微有点违反直觉的行为。当使用 iexact
或 contains
查询集中的筛选器。这种行为分为两种情况:
1。对于子字符串匹配,所有匹配都是不敏感的。这是一个过滤器,例如 filter(name__contains="aa")
将匹配的名称 "Aabb"
.
2。对于包含ASCII范围之外的字符的字符串,即使将不区分大小写的选项传递到查询中,也会区分大小写执行所有精确的字符串匹配。所以 iexact
筛选器的行为将与 exact
在这些情况下过滤。
一些可能的解决办法是 documented at sqlite.org 但是Django中的默认sqlite后端没有使用它们,因为合并它们将非常困难。因此,Django公开默认的sqlite行为,在执行不区分大小写或子字符串筛选时,应该注意这一点。
SQLite没有真正的decimal内部类型。十进制值在内部转换为 REAL
数据类型(8字节IEEE浮点数),如 `SQLite datatypes documentation`_ _,因此它们不支持正确舍入的十进制浮点运算。
sqlite是一个轻量级数据库,因此不能支持高级别的并发性。 OperationalError: database is locked
错误表明应用程序的并发性比 sqlite
可以在默认配置中处理。此错误意味着一个线程或进程在数据库连接上具有独占锁,另一个线程在等待释放锁时超时。
python的sqlite包装器有一个默认超时值,该值确定允许第二个线程在锁超时之前等待多长时间,并引发 OperationalError: database is locked
错误。
如果出现此错误,可以通过以下方法解决:
切换到另一个数据库后端。在某一点上,对于真实的应用程序来说,sqlite变得过于“lite”,并且这些并发错误表明您已经达到了这个程度。
重写代码以减少并发性并确保数据库事务是短期的。
通过设置 timeout
数据库选项:
"OPTIONS": {
# ...
"timeout": 20,
# ...
}
这将使SQLite在抛出“databaseislocked”错误之前等待一段时间;它不会真正解决这些错误。
QuerySet.select_for_update()
不支持¶sqlite不支持 SELECT ... FOR UPDATE
语法。叫它不会有任何效果。
QuerySet.iterator()
¶中描述了一些特殊注意事项。 Isolation In SQLite 在对表进行迭代时使用 QuerySet.iterator()
. 如果在循环中添加、更改或删除了一行,那么该行可能会出现,也可能不会出现,或者可能会出现两次,出现在从迭代器获取的后续结果中。您的代码必须处理这个问题。
使用 JSONField
在SQLite上,您需要启用 JSON1 extension 关于Python的 sqlite3
类库。如果安装时未启用扩展,则系统错误 (fields.E180
)将被提高。
要启用JSON1扩展,可以按照 the wiki page .
备注
默认情况下,在SQLite 3.38+上启用JSON1扩展。
Django支持 Oracle Database Server 版本19c及更高版本。1.3.2版或更高版本的 oracledb 需要使用Python驱动程序。
自 5.0 版本弃用: 支持 cx_Oracle
已弃用。
为了 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自己的测试套件是必需的。
所有这些特权都包含在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或轻松连接字符串可用于 NAME
如果两者 HOST
和 PORT
是空的。使用rac或可插拔数据库时,如果没有 tnsnames.ora
例如。
轻松连接字符串示例:
"NAME": "localhost:1521/orclpdb1"
完整DSN字符串示例:
"NAME": (
"(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521))"
"(CONNECT_DATA=(SERVICE_NAME=orclpdb1)))"
)
如果计划在多线程环境中运行Django(例如,在任何现代操作系统上使用默认MPM模块的Apache),那么 must 设置 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之外,这些引号没有任何效果。
运行时 migrate
,一个 ORA-06552
如果某些Oracle关键字用作模型字段的名称或 db_column
选择权。Django引用查询中使用的所有标识符,以避免大多数此类问题,但当Oracle数据类型用作列名时,仍然可能发生此错误。尤其要注意避免使用这些名称 date
, timestamp
, number
或 float
作为字段名。
Django通常喜欢使用空字符串 (''
)而不是 NULL
但甲骨文对这两者的处理是相同的。为了解决这个问题,Oracle后端会忽略 null
选项,用于将空字符串作为可能值并生成DDL的字段 null=True
. 从数据库提取时,假定 NULL
其中一个字段中的值实际上意味着空字符串,数据将被静默转换以反映此假设。
TextField
局限性¶Oracle后端存储 TextFields
作为 NCLOB
柱。Oracle通常会对此类LOB列的使用施加一些限制:
LOB列不能用作主键。
在索引中不能使用LOB列。
LOB列不能用于 SELECT DISTINCT
名单。这意味着尝试使用 QuerySet.distinct
模型上的方法,其中包括 TextField
列将导致 ORA-00932
对Oracle运行时出错。作为解决方案,使用 QuerySet.defer
方法与 distinct()
预防 TextField
列中包含的列 SELECT DISTINCT
名单。
Django带有内置的数据库后端。您可以将现有数据库后端子类化以修改其行为、特性或配置。
例如,假设您需要更改单个数据库功能。首先,您必须创建一个具有 base
模块在里面。例如:
mysite/
...
mydbengine/
__init__.py
base.py
这个 base.py
模块必须包含名为 DatabaseWrapper
它从 django.db.backends
模块。下面是一个PostgreSQL引擎子类化以更改功能类的示例 allows_group_by_selected_pks_on_model
:
from django.db.backends.postgresql import base, features
class DatabaseFeatures(features.DatabaseFeatures):
def allows_group_by_selected_pks_on_model(self, model):
return True
class DatabaseWrapper(base.DatabaseWrapper):
features_class = DatabaseFeatures
最后,必须指定 DATABASE-ENGINE
在你 settings.py
文件::
DATABASES = {
"default": {
"ENGINE": "mydbengine",
# ...
},
}
您可以通过查看 django/db/backends .
除了官方支持的数据库外,还有第三方提供的后端,允许您与Django一起使用其他数据库:
这些非官方后端支持的Django版本和ORM功能差异很大。有关这些非官方后端的特定功能的查询,以及任何支持查询,应指向每个第三方项目提供的支持渠道。
12月 18, 2023