数据库¶ T0>

Django试图在所有数据库后端支持尽可能多的功能。 但是,并不是所有的数据库后端都是相同的,我们必须做出设计决定,支持哪些功能以及我们可以安全地进行哪些假设。

该文件描述了一些可能与Django使用相关的功能。 当然,这并不是要替代服务器特定的文档或参考手册。

一般说明

持久连接

持久连接避免了在每个请求中重新建立与数据库的连接的开销。 它们由定义连接的最大生命周期的CONN_MAX_AGE参数控制。 它可以为每个数据库独立设置。

缺省值是0,保留每个请求结束时关闭数据库连接的历史行为。 要启用持续连接,请将CONN_MAX_AGE设置为正数秒。 对于无限制的持续连接,将其设置为None

连接管理

Django在首次进行数据库查询时打开数据库的连接。 它保持这个连接打开并在随后的请求中重用。 一旦Django超过CONN_MAX_AGE定义的最大年限,或者当它不再可用时,它将关闭连接。

详细地说,Django自动打开一个到数据库的连接,只要它需要一个连接,并且没有一个 - 因为这是第一个连接,或者因为之前的连接已关闭。

在每个请求开始时,如果Django达到其最大年龄,则关闭连接。 如果您的数据库在一段时间后终止空闲连接,则应将CONN_MAX_AGE设置为较低的值,以便Django不会尝试使用已由数据库服务器终止的连接。 (这个问题可能只会影响非常低的流量网站。)

在每个请求结束时,如果Django已达到最大年龄或者处于不可恢复的错误状态,则关闭连接。 如果在处理请求时发生任何数据库错误,Django会检查连接是否仍然有效,如果没有连接就关闭。 因此,数据库错误至多影响一个请求;如果连接变得不可用,则下一个请求会重新建立连接。

警告¶ T0>

由于每个线程维护自己的连接,因此您的数据库必须至少支持与工作线程同时连接的同时连接数。

有时一个数据库不会被大多数视图访问,例如因为它是外部系统的数据库,或者感谢缓存。 In such cases, you should set CONN_MAX_AGE to a low value or even 0, because it doesn’t make sense to maintain a connection that’s unlikely to be reused. 这将有助于保持与这个数据库同时连接的数量很小。

开发服务器为其处理的每个请求创建一个新线程,否定持久连接的效果。 在开发过程中不要启用它们。

当Django建立到数据库的连接时,它根据所使用的后端设置适当的参数。 如果启用持续连接,则此设置不再重复每个请求。 如果修改连接的隔离级别或时区等参数,则应该在每个请求结束时恢复Django的默认值,在每个请求开始时强制一个适当的值,或者禁用持久连接。

编码¶ T0>

Django假定所有数据库都使用UTF-8编码。 使用其他编码可能会导致意外的行为,例如数据库中的“value too long”错误,以用于在Django中有效的数据。 有关如何正确设置数据库的信息,请参阅下面的数据库特定注释。

PostgreSQL记录

Django支持PostgreSQL 9.3及更高版本。 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' by default, or the value set in the connection options (see below),
  • timezone: 'UTC' when USE_TZ is True, value of TIME_ZONE otherwise.

如果这些参数已经具有正确的值,那么Django不会为每个新的连接设置它们,这会稍微提高性能。 您可以直接在postgresql.conf中配置它们,或者使用ALTER ROLE更方便地为每个数据库用户配置它们。

Django在没有这个优化的情况下工作得很好,但是每个新的连接都会做一些额外的查询来设置这些参数。

隔离级别

像PostgreSQL本身一样,Django默认为READ COMMITTED 隔离级别 If you need a higher isolation level such as REPEATABLE READ or SERIALIZABLE, set it in the OPTIONS part of your database configuration in DATABASES:

import psycopg2.extensions

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

注意

在更高的隔离级别下,应用程序应该准备好处理序列化失败时引发的异常。 该选项是为高级用途而设计的。

varchartext列的索引

在模型字段上指定db_index=True时,Django通常会输出一个CREATE INDEX语句。 However, if the database type for the field is either varchar or text (e.g., used by CharField, FileField, and TextField), then Django will create an additional index that uses an appropriate PostgreSQL operator class for the column. containsstartswith查找类型所做的那样,额外索引对于正确执行在其SQL中使用LIKE运算符的查找是必需的。

用于添加扩展名的迁移操作

如果您需要使用迁移来添加PostgreSQL扩展(如hstorepostgis等),请使用CreateExtension操作。

服务器端游标

Django 1.11新增功能

当使用QuerySet.iterator()时,Django打开server-side cursor 默认情况下,PostgreSQL假定只有前10%的游标查询的结果会被提取。 查询计划者花费更少的时间计划查询,并开始更快地返回结果,但如果检索结果超过10%,这可能会降低性能。 PostgreSQL对游标查询检索行数的假设是由cursor_tuple_fraction选项控制的。

事务池和服务器端游标

Django新增1.11.1。

在事务池模式(例如pgBouncer)中使用连接池需要禁用该连接的服务器端游标。

服务器端游标是连接本地的,当AUTOCOMMITTrue时,在事务结束时保持打开状态。 后续事务可能会尝试从服务器端游标获取更多结果。 在事务池模式下,不保证后续事务将使用相同的连接。 如果使用不同的连接,则当事务引用服务器端游标时会引发错误,因为服务器端游标只能在创建它们的连接中访问。

一种解决方法是通过将DISABLE_SERVER_SIDE_CURSORS设置为True来禁用DATABASES中的连接的服务器端游标。

为了从事务池模式中的服务器端游标中受益,可以设置another connection to the database以执行使用服务器端游标的查询。 此连接需要直接连接到数据库或会话池模式的连接池。

另一个选择是使用服务器端游标在atomic()块中包装每个QuerySet,因为它在事务期间禁用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编码)并委托给它执行事务和参照完整性的任务。 在使用MyISAM存储引擎时,注意到后两个实际上并没有被MySQL强制执行,这一点很重要,请参阅下一节。

存储引擎

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社区服务器安装程序将InnoDB设置为默认存储引擎。

MySQL DB API驱动程序

MySQL有一些实现 PEP 249中描述的Python数据库API的驱动程序:

  • mysqlclient is a native driver. 这是推荐的选择
  • MySQL Connector/Python is a pure Python driver from Oracle that does not require the MySQL client library or any Python modules outside the standard library.

这些驱动程序是线程安全的并提供连接池。

除了DB API驱动程序之外,Django还需要一个适配器才能从ORM访问数据库驱动程序。 Django provides an adapter for mysqlclient while MySQL Connector/Python includes its own.

的mysqlclient ¶ T0>

Django需要mysqlclient 1.3.7或更高版本。

MySQL连接器/ Python

MySQL Connector / Python可以从下载页面中找到。 Django适配器在版本1.1.X和更高版本中可用。 它可能不支持最新版本的Django。

时区定义

如果您打算使用Django的timezone support,请使用mysql_tzinfo_to_sql将时区表加载到MySQL数据库中。 这只需要为MySQL服务器完成一次,而不是每个数据库。

创建你的数据库

您可以使用命令行工具和此SQL来创建数据库

CREATE DATABASE <dbname> CHARACTER SET utf8;

这确保所有表和列默认使用UTF-8。

整理设置

列的排序规则设置控制数据排序的顺序以及字符串比较的顺序。 它可以在数据库级别设置,也可以在每个表格和每列设置。 This is documented thoroughly in the MySQL documentation. 在所有情况下,都可以通过直接操作数据库表来设置排序规则。 Django没有提供在模型定义上设置的方法。

默认情况下,使用UTF-8数据库,MySQL将使用utf8_general_ci排序规则。 这导致所有字符串相等比较都是以不区分大小写的方式完成的。 That is, "Fred" and "freD" are considered equal at the database level. 如果你对一个字段有一个唯一的限制,那么试图将"aa""AA"插入同一列是非法的,因为它们相等(因此,非唯一的)与默认排序规则。 如果您希望对特定列或表进行区分大小写的比较,请更改列或表以使用utf8_bin归类。

请注意,根据MySQL Unicode字符集,与utf8_unicode_ci的比较,utf8_general_ci归类的比较速度更快,但是正确性稍差。 如果你的应用程序可以接受,你应该使用utf8_general_ci,因为它更快。 如果这是不可接受的(例如,如果您需要德语字典顺序),请使用utf8_unicode_ci,因为它更准确。

警告

模型表单以区分大小写的方式验证唯一字段。 因此,在使用不区分大小写的排序规则时,只有大小写不同的唯一字段值的formset才会通过验证,但在调用save()时,将会引发IntegrityError

连接到数据库

请参阅settings documentation

连接设置按以下顺序使用:

  1. OPTIONS
  2. NAME, USER, PASSWORD, HOST, PORT
  3. MySQL选项文件。

换句话说,如果你在OPTIONS中设置数据库的名字,这将优先于NAME,它将覆盖MySQL选项文件 T6>。

以下是使用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连接选项可能是有用的,比如sslinit_commandsql_mode

设置sql_mode

从MySQL 5.7开始,新安装的MySQL 5.6中,sql_mode选项的默认值包含STRICT_TRANS_TABLES 这个选项在数据被插入时被截断时会将警告升级为错误,所以Django强烈建议为MySQL启用一个严格模式以防止数据丢失(STRICT_TRANS_TABLESSTRICT_ALL_TABLES

如果你需要自定义SQL模式,你可以像其他MySQL选项那样设置sql_mode变量​​:在配置文件中或者使用条目 'init_command': “组 的sql_mode = 'STRICT_TRANS_TABLES'” DATABASES中的数据库配置的OPTIONS部分。

隔离级别

Django 1.11新增功能

在运行并发加载时,来自不同会话的数据库事务(比如,处理不同请求的独立线程)可以相互交互。 这些交互受到每个会话的事务隔离级别的影响。 您可以使用DATABASES中的数据库配置的OPTIONS部分中的'isolation_level'条目来设置连接的隔离级别。 此条目的有效值是四个标准隔离级别:

  • '读取 未提交'
  • '读取 提交'
  • '可重复 读取
  • “序列化”

None来使用服务器配置的隔离级别。 不过,Django最好使用并默认读取提交,而不是MySQL默认的可重复读取。 数据丢失是可能的重复阅读。

在Django 2.0中更改:

在旧版本中,MySQL数据库后端默认使用数据库的隔离级别(默认为可重复读取),而不是读取提交。

创建你的表

当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;
    

    如果你有很多表格,这可能是单调乏味的。

  • 另一种选择是在创建表之前使用MySQLdb的init_command选项:

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

    这将在连接到数据库时设置默认的存储引擎。 在创建表之后,应删除此选项,因为它只在创建表时将需要的查询添加到每个数据库连接。

表名

即使在最新版本的MySQL中,也有已知问题,当某些SQL语句在特定条件下执行时,可能会导致表名的情况发生改变。 建议您尽可能使用小写的表名,以避免此行为可能引起的任何问题。 当从模型中自动生成表名时,Django使用小写的表名,所以如果通过db_table参数覆盖表名,主要考虑这一点。

保存点¶ T0>

Django ORM和MySQL(当使用InnoDB storage engine时)都支持数据库savepoints

如果您使用MyISAM存储引擎,请注意,如果您尝试使用交易API的savepoint-related methods of the transactions API,您将收到数据库生成的错误。 原因是检测MySQL数据库/表的存储引擎是一个昂贵的操作,所以决定在这样的检测结果的基础上动态转换这些方法是不值得的。

特定字段的注释

字符字段

如果对字段使用unique=True,那么使用VARCHAR列类型存储的任何字段的max_length限制为255个字符。 这会影响CharFieldSlugField

TextField的局限性

MySQL只能索引BLOBTEXT列的前N个字符。 由于TextField没有定义的长度,因此不能将其标记为unique=True MySQL will report: “BLOB/TEXT column ‘<db_column>’ used in key specification without a key length”.

时间和日期时间字段的分数秒支持

MySQL 5.6.4 and later can store fractional seconds, provided that the column definition includes a fractional indication (e.g. DATETIME(6)). 较早的版本根本不支持它们。

如果数据库服务器支持,Django将不会升级现有的列以包含小数秒。 如果要在现有数据库上启用它们,则需要手动更新目标数据库上的列,方法是执行如下命令:

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

或者在data migration中使用RunSQL操作。

TIMESTAMP

If you are using a legacy database that contains TIMESTAMP columns, you must set USE_TZ = False to avoid data corruption. inspectdb maps these columns to DateTimeField and if you enable timezone support, both MySQL and Django will attempt to convert the values from UTC to local time.

使用QuerySet.select_for_update()

MySQL不支持NOWAITSKIP LOCKEDOF选项 选择 ... 对于 UPDATE 声明。 If select_for_update() is used with nowait=True, skip_locked=True, or of then a NotSupportedError is raised.

自动类型转换可能会导致意外的结果

在对字符串类型执行查询时,如果使用整数值,则在执行比较之前,MySQL将强制将表中所有值的类型转换为整数。 If your table contains the values 'abc', 'def' and you query for WHERE mycolumn=0, both rows will match. 类似地,WHERE mycolumn = 1将匹配值'abc1' 因此,包含在Django中的字符串类型字段在查询中使用它之前总是将该值转换为字符串。

If you implement custom model fields that inherit from Field directly, are overriding get_prep_value(), or use RawSQL, extra(), or raw(), you should ensure that you perform appropriate typecasting.

SQLite注释

SQLite provides an excellent development alternative for applications that are predominantly read-only or require a smaller installation footprint. 就像所有的数据库服务器一样,SQLite特有的差异也是你应该知道的。

子字符串匹配和区分大小写

对于所有的SQLite版本,当试图匹配某些类型的字符串时,会有一些反直觉行为。 当在Querysets中使用iexactcontains过滤器时,会触发这些操作。 行为分为两种情况:

1. 对于子字符串匹配,所有匹配都是不区分大小写的。 这是一个过滤器,如filter(name__contains="aa")将匹配"Aabb"的名称。

2. 对于包含ASCII范围之外的字符的字符串,即使在不区分大小写的选项传递到查询中时,所有精确的字符串匹配也会以区分大小写的方式执行。 因此,在这些情况下,iexact过滤器的行为与exact过滤器的行为完全相同。

一些可能的解决方法是在sqlite.org 中记录,但是它们并没有被Django中的默认SQLite后端使用,因为合并它们将是相当困难的。 因此,Django公开了默认的SQLite行为,并且在执行不区分大小写或子字符串过滤时应该注意到这一点。

“数据库被锁定”错误

SQLite是一个轻量级的数据库,因此不能支持高水平的并发。 OperationalError: 数据库 锁定 错误表明您的应用程序正在经历比sqlite在默认配置下可以处理更多的并发性。 这个错误意味着一个线程或进程在数据库连接上有一个独占锁,另一个线程超时等待锁被释放。

Python的SQLite包装器有一个默认的超时值,它决定了第二个线程在超时前允许等待的时间,并提高 OperationalError: 数据库 锁定 错误。

如果你得到这个错误,你可以通过以下方式解决:

  • 切换到另一个数据库后端。 在某个时刻,SQLite对于真实世界的应用程序变得太“精简”了,这些并发性错误表明你已经达到了这一点。

  • 重写你的代码来降低并发性,并确保数据库事务是短暂的。

  • 通过设置timeout数据库选项增加默认超时值:

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

    在抛出“数据库被锁定”错误之前,这只会让SQLite等待一会儿;它不会真的做任何事情来解决它们。

QuerySet.select_for_update()

SQLite不支持 选择 ... 对于 UPDATE 句法。 调用它将不起作用。

不支持原始查询中的“pyformat”参数样式

对于大多数后端,原始查询(Manager.raw()cursor.execute())可以使用“pyformat”参数样式, '%(name)s',参数作为字典而不是列表传递。 SQLite不支持这个。

Oracle注释

Django支持Oracle数据库服务器版本12.1和更高版本。 需要cx_Oracle Python驱动程序的版本5.2或更高版本。

为了使python manage.py migrate命令正常工作,您的Oracle数据库用户必须具有运行权限以下命令:

  • 创建表
  • 创建序列
  • 创建过程
  • CREATE TRIGGER

要运行项目的测试套件,用户通常需要这些额外的特权:

  • 创建用户
  • 改变用户
  • DROP USER
  • 创建表空间
  • DROP TABLESPACE
  • 使用管理员选项创建会话
  • 使用ADMIN选项创建表
  • 使用管理员选项创建序列
  • 使用管理员选项创建过程
  • 使用管理员选项创建触发器

请注意,尽管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_LOBSYS.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': '',
    }
}

在这种情况下,您应该将HOSTPORT都留空。 However, if you don’t use a tnsnames.ora file or a similar naming method and want to connect using the SID (“xe” in this example), then fill in both HOST and PORT like so:

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

您应该提供HOSTPORT,或者将两者都留为空字符串。 Django将根据该选择使用不同的连接描述符。

Threaded选项

If you plan to run Django in a multithreaded environment (e.g. Apache using the default MPM module on any modern operating system), then you must set the threaded option of your Oracle database configuration to True:

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

不这样做可能会导致崩溃和其他奇怪的行为。

INSERT ...返回到

默认情况下,Oracle后端使用RETURNING INTO子句来高效地检索AutoField行。 This behavior may result in a DatabaseError in certain unusual setups, such as when inserting into a remote table, or into a view with an INSTEAD OF trigger. The RETURNING INTO clause can be disabled by setting the use_returning_into option of the database configuration to 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之外,引号不起作用。

When running migrate, an ORA-06552 error may be encountered if certain Oracle keywords are used as the name of a model field or the value of a db_column option. Django引用查询中使用的所有标识符来防止大多数此类问题,但是当使用Oracle数据类型作为列名时,仍会发生此错误。 尤其要注意避免使用名称datetimestampnumberfloat作为字段名称。

NULL和空字符串

Django通常倾向于使用空字符串('')而不是NULL,但是Oracle对待这两者是相同的。 为了解决这个问题,Oracle后端会忽略空字符串作为可能值并生成DDL的字段的显式null选项,就像null=True一样。 When fetching from the database, it is assumed that a NULL value in one of these fields really means the empty string, and the data is silently converted to reflect this assumption.

TextField的局限性

Oracle后端将TextFields存储为NCLOB列。 一般来说,Oracle对这种LOB列的使用施加了一些限制:

  • LOB列不能用作主键。
  • LOB列不能在索引中使用。
  • LOB列不能在SELECT DISTINCT列表中使用。 这意味着试图在包含TextField列的模型上使用QuerySet.distinct方法将导致在运行时出现ORA-00932错误甲骨文。 As a workaround, use the QuerySet.defer method in conjunction with distinct() to prevent TextField columns from being included in the SELECT DISTINCT list.

使用第三方数据库后端

除官方支持的数据库外,第三方还提供后端,使您可以使用其他数据库与Django:

这些非官方后端支持的Django版本和ORM功能差别很大。 对于这些非官方后端的具体功能的质疑以及任何支持查询,都应该针对每个第三方项目提供的支持渠道。