---
title: "将你的应用从 Django 0.96 移植到 1.0"
version: 6.1
locale: zh-hans
source: https://docs.djangoproject.com/zh-hans/6.1/releases/1.0-porting-guide/
canonical: https://djangodocs.dev/zh-hans/6.1/releases/1.0-porting-guide/
---
# 将你的应用从 Django 0.96 移植到 1.0

Django 1.0 在某些地方与 0.96 版本是不兼容的。

这个指南会帮助你把 0.96 的项目和应用移植到 1.0 版本。本文档的第一部分包含了需要运行在 1.0上的常见变更。如果通过了第一部分的变更，你的代码依然无法运行，那么请检查 [Less-common Changes](#less-common-changes) 不常见的变更部分中列出的兼容问题。

> **See also**
>
> 文档 [1.0 版本注意事项](/zh-hans/6.1/releases/1.0/)。这份文档更深入地解释了 1.0 中新的特性；移植指南更多考虑了帮助你快速更新你的代码。

## 常见变更

本部分描述了 0.96 与 1.0 之间的变更，这些变更都是大部分用户会做的事情。

### 使用 Unicode 字符集

逐字地把字符串 (`'foo'`) 变成 Unicode 字符串 (`u'foo'`)。Django 目前从始至终贯穿地使用 Unicode 字符集字符串。在绝大多数地方，生食字符串会继续有效，但更新成 Unicode 字符串会防止某些含糊的问题出现。

查阅 [Unicode 数据](/zh-hans/6.1/ref/unicode/) 文档了解细节。

### 模型

对于你的模型文件中常见的变更：

#### `maxlength` 重命名为 `max_length`

把你的 `maxlength` 参数名变成 `max_length` (这次参数名的变更是为了与表单区域保持一致)：

#### 用 `__unicode__` 代替 `__str__`

使用 `__unicode__` 方法替换你的模型中的 `__str__` 函数，然后才能确保你使用 [使用 Unicode 字符集](#use-unicode) (`u'foo'`) 中所介绍的方法。

#### 移除 `prepopulated_from`

删除模型区域中 `prepopulated_from` 参数。这个参数不再合法，而且已经转移到管理员 `admin.py` 模块里的 `ModelAdmin` 类中去了。查阅 [管理员](#the-admin) 内容了解更多对管理员变更的细节。

#### 移除 `core`

删除你的模型区域里的 `core` 参数。这个参数不再需要了，因为相同功能 (参考 [行内编辑](/zh-hans/6.1/ref/contrib/admin/#admin-inlines)) 目前已经由后台接口做出不同地处理。你不用再担心行内编辑，除非你在 [管理员](#the-admin) 部分才考虑行内编辑。目前，删除所有对 `core` 参数的指向。

#### 用 `admin.py` 替换  `class Admin:`

从你的模型里移除所有嵌入 `class Admin` 管理员类声明。如果你保留这种类的话，不会对任何有影响，但也不会起任何作用。要注册应用程序管理员，你要把这种类的声明移到 `admin.py` 管理员模块文件里；查看 [管理员](#the-admin) 内容了解更多细节。

> **See also**
>
> 对 [djangosnippets](https://djangosnippets.org/) 做出的贡献者已经写了一个脚本会 [扫描你的 models.py 模型模块后生成一个相应的 admin.py 管理员模块](https://djangosnippets.org/snippets/603/)。

#### 例如

下面的一个例子 `models.py` 模型文件含有所有你需要做出的变更：

老版本 (0.96) `models.py`:

```
class Author(models.Model):
    first_name = models.CharField(maxlength=30)
    last_name = models.CharField(maxlength=30)
    slug = models.CharField(maxlength=60, prepopulate_from=("first_name", "last_name"))

    class Admin:
        list_display = ["first_name", "last_name"]

    def __str__(self):
        return "%s %s" % (self.first_name, self.last_name)
```

新版本 (1.0) `models.py`:

```
class Author(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)
    slug = models.CharField(max_length=60)

    def __unicode__(self):
        return "%s %s" % (self.first_name, self.last_name)
```

新版本 (1.0) `admin.py` 管理员模块：

```
from django.contrib import admin
from models import Author

class AuthorAdmin(admin.ModelAdmin):
    list_display = ["first_name", "last_name"]
    prepopulated_fields = {"slug": ("first_name", "last_name")}

admin.site.register(Author, AuthorAdmin)
```

### 管理员

在 1.0 版本中最具挑战性的新管理员功能问题之一。Django 管理接口 (`django.contrib.admin`) 管理员功能已经完全重构了；许多管理员定义目前都完全从许多模型定义中解构出来，许多框架都重写后使用 Django 的新表单处理库，而且重新设计成具有扩展和自定义能力。

实际中，意味着你要重写所有你的 `class Admin` 管理员类声明。你已经在上面的 [models](#models) 中见过了如何替换你的 `class Admin` 管理员类，就是在 `admin.py` 管理员模块文件中用一个 `admin.site.register()` 管理员网页注册调用来替代。下面这些都是一些更详细的如何重写 `Admin` 管理员声明类的新句法。

#### 使用新的行内句法

新的 `edit_inline` 行内编辑选项都已经移到 `admin.py` 管理员模块中了。下面有一个例子：

老版本 (0.96):

```
class Parent(models.Model): ...

class Child(models.Model):
    parent = models.ForeignKey(Parent, edit_inline=models.STACKED, num_in_admin=3)
```

新版本 (1.0):

```
class ChildInline(admin.StackedInline):
    model = Child
    extra = 3

class ParentAdmin(admin.ModelAdmin):
    model = Parent
    inlines = [ChildInline]

admin.site.register(Parent, ParentAdmin)
```

查阅 [InlineModelAdmin 对象](/zh-hans/6.1/ref/contrib/admin/#admin-inlines) 管理员行内文档了解更多细节。

#### 简化 `fields`，或使用 `fieldsets`

老的 `fields` 句法是非常迷糊的，而且已经被简化过。老的句法依然有效，但你要使用 `fieldsets` 来代替老旧句法。

老版本 (0.96):

```
class ModelOne(models.Model):
    ...

    class Admin:
        fields = ((None, {"fields": ("foo", "bar")}),)

class ModelTwo(models.Model):
    ...

    class Admin:
        fields = (
            ("group1", {"fields": ("foo", "bar"), "classes": "collapse"}),
            ("group2", {"fields": ("spam", "eggs"), "classes": "collapse wide"}),
        )
```

新版本 (1.0):

```
class ModelOneAdmin(admin.ModelAdmin):
    fields = ("foo", "bar")

class ModelTwoAdmin(admin.ModelAdmin):
    fieldsets = (
        ("group1", {"fields": ("foo", "bar"), "classes": "collapse"}),
        ("group2", {"fields": ("spam", "eggs"), "classes": "collapse wide"}),
    )
```

> **See also**
>
> - 更多关于变更的详细信息以及背后的原因都可以在 [NewformsAdminBranch wiki page](https://code.djangoproject.com/wiki/NewformsAdminBranch) 新表单管理分支维基百科页面找到
> - 新的管理员功能伴随着许多新特性；你可以在 [管理员文档](/zh-hans/6.1/ref/contrib/admin/) 中来阅读有关内容。

### URLs

#### 更新你的根路径 `urls.py` 模块

如果你正在使用后台界面，你需要更新你的根路径\`\`urls.py\`\` 模块。

老版本 (0.96) `urls.py`:

```
from django.conf.urls.defaults import *

urlpatterns = patterns(
    "",
    (r"^admin/", include("django.contrib.admin.urls")),
    # ... the rest of your URLs here ...
)
```

新版本 (1.0) `urls.py`:

```
from django.conf.urls.defaults import *

# The next two lines enable the admin and load each admin.py file:
from django.contrib import admin

admin.autodiscover()

urlpatterns = patterns(
    "",
    (r"^admin/(.*)", admin.site.root),
    # ... the rest of your URLs here ...
)
```

### 视图

#### 使用 `django.forms` 来代替 `newforms` 用法

用 `django.forms` 来替换 `django.newforms` 用法 -- Django 1.0 版本重命名了 `newforms` 模块名 (曾用在 0.96 版本的名字) 采用以前用过的 `forms` 名字。而 `oldforms` 模块也会被移除。

如果你已经使用 `newforms` 库的话，而且你采用了我们所建议的 `import` 导入语句句法，那么所有你要做的就是改变一下你的导入依据即可。

老版本:

```
from django import newforms as forms
```

新版本:

```
from django import forms
```

如果你正在使用老的表单系统 (正规的名字是 `django.forms` 和 `django.oldforms`)，那么你要重写你的表单。良好地开始就是从阅读 [表单文档](/zh-hans/6.1/topics/forms/) 内容

#### 处理上传文件使用新的 API

代替上传文件的用法 -- 那就是，采用 `request.FILES` 文件请求入口 -- 与含有 [`UploadedFile`](/zh-hans/6.1/ref/files/uploads/#django.core.files.uploadedfile.UploadedFile) 文件上传类的简单字典一样。老的字典句法不再有效了。

因此，看起来就像:

```
def my_view(request):
    f = request.FILES["file_field_name"]
    ...
```

...你需要做出如下变更：

| 老版本 (0.96) | 新版本 (1.0) |
| --- | --- |
| `f['content']` | `f.read()` |
| `f['filename']` | `f.name` |
| `f['content-type']` | `f.content_type` |

#### 文件字段使用新API处理

class:django.db.models.FileField 的内部实现已更改。一个明显的结果是您访问特殊属性(URL, filename, image size, 等等)的方式发生了变化。您需要进行以下更改，假设您的模型 [`FileField`](/zh-hans/6.1/ref/models/fields/#django.db.models.FileField) 调用 `myfile`:

| 老版本 (0.96) | 新版本 (1.0) |
| --- | --- |
| `myfile.get_content_filename()` | `myfile.content.path` |
| `myfile.get_content_url()` | `myfile.content.url` |
| `myfile.get_content_size()` | `myfile.content.size` |
| `myfile.save_content_file()` | `myfile.content.save()` |
| `myfile.get_content_width()` | `myfile.content.width` |
| `myfile.get_content_height()` | `myfile.content.height` |

请注意 `width` 和 `height` 属性仅对:class:~django.db.models.ImageField  字段有意义。更多详细信息可以在 [模型 API](/zh-hans/6.1/ref/models/fields/) 文档中找到。

#### 使用 `Paginator` 而不是 `ObjectPaginator`

0.96 版本中的 `ObjectPaginator` 已被删除，并替换为一个改进版本: class:django.core.paginator.Paginator。

### 模板

#### 学会爱上自动转义

默认情况下，模板系统现在会自动对每个变量的输出进行HTML转义。要了解更多信息，请参阅 [自动 HTML 转义](/zh-hans/6.1/ref/templates/language/#automatic-html-escaping)。

要禁用单个变量的自动转义，请使用 [`safe`](/zh-hans/6.1/ref/templates/builtins/#std-templatefilter-safe) 过滤器:

```html+django
This will be escaped: {{ data }}
This will not be escaped: {{ data|safe }}
```

要禁用整个模板的自动转义，请将模板（或模板的特定部分）包装在 [`autoescape`](/zh-hans/6.1/ref/templates/builtins/#std-templatetag-autoescape) 标签:

```html+django
{% autoescape off %}
   ... unescaped template content here ...
{% endautoescape %}
```

## 不常见的变化

以下更改是较小的、更本地化的更改。它们应该只影响更高级的用户，但是通读列表并检查代码中的这些东西可能是值得的。

### 信号

- 将\`\`\*\*kwargs\`\`添加到任何注册的信号处理程序中。
- 通过 [`Signal`](/zh-hans/6.1/topics/signals/#django.dispatch.Signal) 对象上的方法连接、断开连接和发送信号，而不是通过 `django.dispatch.dispatcher` 中的模块方法。
- 移除任何对 `Anonymous` 和 `Any` 发送者选项的使用；它们不再存在。你仍然可以通过使用 `sender=None` 接收来自任何发送者的信号。
- 将你声明的任何自定义信号转换为 [`django.dispatch.Signal`](/zh-hans/6.1/topics/signals/#django.dispatch.Signal) 的实例，而不是匿名对象。

以下是你需要进行的代码更改的快速摘要：

| 老版本 (0.96) | 新版本 (1.0) |
| --- | --- |
| `def callback(sender)` | `def callback(sender, **kwargs)` |
| `sig = object()` | `sig = django.dispatch.Signal()` |
| `dispatcher.connect(callback, sig)` | `sig.connect(callback)` |
| `dispatcher.send(sig, sender)` | `sig.send(sender)` |
| `dispatcher.connect(callback, sig, sender=Any)` | `sig.connect(callback, sender=None)` |

### 评论

如果你使用的是Django 0.96版的\` Django .contrib.comments\`应用程序，你需要升级到1.0版引入的新评论应用程序。详细信息请参见升级指导书。

### 模板标签

#### [`spaceless`](/zh-hans/6.1/ref/templates/builtins/#std-templatetag-spaceless) 标签

`spaceless` 模板标签现在会移除 HTML 标签之间的 *所有* 空格，而不再保留单个空格。

### 本地风味

#### 美国本地风味

`django.contrib.localflavor.usa` 已重命名为 `django.contrib.localflavor.us`。此更改是为了与其他本地化风格的命名方案匹配。要迁移你的代码，你只需要更改导入语句。

### 会话

#### 获取新的会话密钥

`SessionBase.get_new_session_key()` 已重命名为 `_get_new_session_key()`。`get_new_session_object()` 不再存在。

### 辅助工具

#### 加载一行不再调用"save()"

以前加载一行数据会自动运行模型的\`save()\`方法。现在情况不再是这样了，所以任何由\`\`save()\`\`自动填充的字段(例如:时间戳)现在都需要在任何fixture中显示值。

### 配置

#### 更好的异常处理

旧的 [`EnvironmentError`](https://docs.python.org/3/library/exceptions.html#EnvironmentError) 现已拆分为 [`ImportError`](https://docs.python.org/3/library/exceptions.html#ImportError) （当 Django 无法找到设置模块时）和 [`RuntimeError`](https://docs.python.org/3/library/exceptions.html#RuntimeError) （当你尝试在已经使用过设置之后重新配置它们时）。

#### [`LOGIN_URL`](/zh-hans/6.1/ref/settings/#std-setting-LOGIN_URL) 已移动

[`LOGIN_URL`](/zh-hans/6.1/ref/settings/#std-setting-LOGIN_URL) 常量已从 `django.contrib.auth` 移动到 `settings` 模块。不再使用 `from django.contrib.auth import LOGIN_URL`，请改用 [`settings.LOGIN_URL`](/zh-hans/6.1/ref/settings/#std-setting-LOGIN_URL)。

#### [`APPEND_SLASH`](/zh-hans/6.1/ref/settings/#std-setting-APPEND_SLASH) 的行为已更新。

在 0.96 版本中，如果一个 URL 不以斜杠结尾，或者其路径的最后一个组件中没有句点，并且 [`APPEND_SLASH`](/zh-hans/6.1/ref/settings/#std-setting-APPEND_SLASH) 为 True，Django 会重定向到相同的 URL，但在末尾添加斜杠。现在，Django 会检查去掉尾部斜杠的模式是否与你的 URL 模式中的某些内容匹配。如果匹配成功，不会进行重定向，因为假定你是有意捕获该模式的。

对大多数人来说，这不需要进行任何更改。然而，有些人的 URL 模式看起来像这样：

```
r"/some_prefix/(.*)$"
```

以前，这些模式会被重定向以添加尾部斜杠。如果你希望这些 URL 始终带有斜杠，请将模式改写为：

```
r"/some_prefix/(.*/)$"
```

### 较小的模型更改

#### 与\`\`get()\`\`不同的异常

现在，管理器返回 [`MultipleObjectsReturned`](/zh-hans/6.1/ref/exceptions/#django.core.exceptions.MultipleObjectsReturned) 异常，而不再返回 [`AssertionError`](https://docs.python.org/3/library/exceptions.html#AssertionError) 异常：

老版本 (0.96):

```
try:
    Model.objects.get(...)
except AssertionError:
    handle_the_error()
```

新版本 (1.0):

```
try:
    Model.objects.get(...)
except Model.MultipleObjectsReturned:
    handle_the_error()
```

#### `LazyDate` 已删除。

`LazyDate` 帮助类不再存在。

默认字段值和查询参数都可以是可调用对象，因此可以将 `LazyDate` 的实例替换为对 `datetime.datetime.now` 的引用：

老版本 (0.96):

```
class Article(models.Model):
    title = models.CharField(maxlength=100)
    published = models.DateField(default=LazyDate())
```

新版本 (1.0):

```
import datetime

class Article(models.Model):
    title = models.CharField(max_length=100)
    published = models.DateField(default=datetime.datetime.now)
```

#### `DecimalField` 是新的，而 `FloatField` 现在是真正的浮点数字段。

老版本 (0.96):

```
class MyModel(models.Model):
    field_name = models.FloatField(max_digits=10, decimal_places=3)
    ...
```

新版本 (1.0):

```
class MyModel(models.Model):
    field_name = models.DecimalField(max_digits=10, decimal_places=3)
    ...
```

如果你忘记进行这个更改，你会看到关于 `FloatField` 在 `__init__` 中不接受 `max_digits` 属性的错误，因为新的 `FloatField` 不接受与精度相关的参数。

如果你使用的是 MySQL 或 PostgreSQL，不需要进一步的更改。对于 `DecimalField`，数据库列类型与旧的 `FloatField` 相同。

如果你使用的是 SQLite，你需要强制数据库将相应的列视为十进制类型，而不是浮点数。要做到这一点，你需要在对代码进行更改并更新 Django 代码后重新加载数据。

> **Warning**
>
> **首先备份你的数据库!!!!**
>
> 对于SQLite，这意味着要复制存储数据库的单个文件(该文件的名称是\`\`settings.py\`\`文件中的\`\`DATABASE\_NAME\`\`)。

要升级每个应用程序以使用 `DecimalField`，你可以按照以下代码进行操作，将代码中的 `<app>` 替换为每个应用程序的名称：

```console
$ ./manage.py dumpdata --format=xml <app> > data-dump.xml
$ ./manage.py reset <app>
$ ./manage.py loaddata data-dump.xml
```

注意：

1. 在这个过程的第一步中，重要的是记住要使用 XML 格式。我们利用了 XML 数据转储的一个特性，使得将浮点数转换为 SQLite 中的十进制数成为可能。
2. 在第二步中，你将被要求确认你是否准备好丢失相关应用程序的数据。选择是；我们将在第三步中恢复这些数据。
3. 在这个更改之前，Django 附带的应用程序中没有使用 `DecimalField`，所以你不需要担心为任何标准的 Django 模型执行此过程。

如果上述过程出现问题，只需将备份的数据库文件复制到原始文件上，然后重新开始。

### 国际化

#### [`django.views.i18n.set_language()`](/zh-hans/6.1/topics/i18n/translation/#django.views.i18n.set_language) 现在要求使用 POST 请求。

以前使用的是 GET 请求。旧的行为意味着可以通过 GET 请求更改状态（用于显示站点的区域设置），这违反了 HTTP 规范的建议。调用此视图的代码必须确保现在进行的是 POST 请求，而不是 GET 请求。这意味着你不能再使用链接来访问视图，而是必须使用某种表单提交方式（例如按钮）。

#### `_()` 不再位于内置函数中

`_()` （其名称为单个下划线的可调用对象）不再被自动添加到内置函数中，也就是说，它不再在每个模块中自动可用。

如果你之前依赖于 `_()` 总是存在，现在应该显式导入 `ugettext` 或 `ugettext_lazy` （如果适用），并自己将其别名为 `_`：

```
from django.utils.translation import ugettext as _
```

### HTTP 请求/响应对象

#### 对于 `HttpRequest` 的字典访问：

`HttpRequest` objects no longer directly support dictionary-style
access; previously, both `GET` and `POST` data were directly
available on the `HttpRequest` object (e.g., you could check for a
piece of form data by using `if 'some_form_key' in request` or by
reading `request['some_form_key']`). This is no longer supported; if
you need access to the combined `GET` and `POST` data, use
`request.REQUEST` instead.

然而，强烈建议你始终明确查找你期望接收的请求类型的字典（`request.GET` 或 `request.POST`）；依赖于组合的 `request.REQUEST` 字典可能会掩盖传入数据的来源。

#### 访问\`\`HTTPResponse\`\` headers

`django.http.HttpResponse.headers` 已重命名为 `_headers`，并且 [`HttpResponse`](/zh-hans/6.1/ref/request-response/#django.http.HttpResponse) 现在直接支持包含检查。所以使用 `if header in response:` 而不是 `if header in response.headers:`。

### 通用关系

#### 通用关系已从核心中移出。

通用关联类 -- `GenericForeignKey` 和 `GenericRelation` -- 已移动到 [`django.contrib.contenttypes`](/zh-hans/6.1/ref/contrib/contenttypes/#module-django.contrib.contenttypes) 模块。

### 测试中

#### [`django.test.Client.login()`](/zh-hans/6.1/topics/testing/tools/#django.test.Client.login) 发生了变化

老版本 (0.96):

```
from django.test import Client

c = Client()
c.login("/path/to/login", "myuser", "mypassword")
```

新版本 (1.0):

```
# ... same as above, but then:
c.login(username="myuser", password="mypassword")
```

### 管理命令

#### 从你的代码中运行管理命令

[`django.core.management`](/zh-hans/6.1/howto/custom-management-commands/#module-django.core.management) 已经进行了大规模的重构。

你的代码中对管理服务的调用现在需要使用 `call_command`。例如，如果你有一些调用 flush 和 load\_data 的测试代码：

```
from django.core import management

management.flush(verbosity=0, interactive=False)
management.load_data(["test_data"], verbosity=0)
```

...你需要更改这段代码为：

```
from django.core import management

management.call_command("flush", verbosity=0, interactive=False)
management.call_command("loaddata", "test_data", verbosity=0)
```

#### 现在子命令必须在选项之前。

`django-admin.py` 和 `manage.py` 现在要求子命令必须在选项之前。因此：

```console
$ django-admin.py --settings=foo.bar runserver
```

...不再起作用，应该改为：

```console
$ django-admin.py runserver --settings=foo.bar
```

### 联合

#### `Feed.__init__` 发生了变化

syndication 框架的 `Feed` 类的 `__init__()` 方法现在将 `HttpRequest` 对象作为其第二个参数，而不是 feed 的 URL。这允许 syndication 框架在不需要 sites 框架的情况下工作。这只影响到子类化 `Feed` 并覆盖 `__init__()` 方法的代码，以及直接调用 `Feed.__init__()` 的代码。

### 数据结构

#### `SortedDictFromList` 已被移除

`django.newforms.forms.SortedDictFromList` 已被移除。`django.utils.datastructures.SortedDict` 现在可以通过元组序列进行实例化。

要更新你的代码：

1. 在原先使用 `django.newforms.forms.SortedDictFromList` 的地方，现在应该使用 `django.utils.datastructures.SortedDict`。
2. 因为 `django.utils.datastructures.SortedDict.copy` 不像 `SortedDictFromList.copy()` 那样返回深拷贝，如果你依赖于深拷贝，你需要更新你的代码。通过直接使用 `copy.deepcopy` 来实现这一点。

### 数据库后端函数

#### 数据库后端函数已经改名。

几乎所有数据库后端级别的函数都已被重命名和/或移动。虽然这些函数没有被文档化，但如果你使用了其中的任何一个函数，你需要修改你的代码，所有这些函数都在 [`django.db`](/zh-hans/6.1/topics/db/#module-django.db) 中：

| 老版本 (0.96) | 新版本 (1.0) |
| --- | --- |
| `backend.get_autoinc_sql` | `connection.ops.autoinc_sql` |
| `backend.get_date_extract_sql` | `connection.ops.date_extract_sql` |
| `backend.get_date_trunc_sql` | `connection.ops.date_trunc_sql` |
| `backend.get_datetime_cast_sql` | `connection.ops.datetime_cast_sql` |
| `backend.get_deferrable_sql` | `connection.ops.deferrable_sql` |
| `backend.get_drop_foreignkey_sql` | `connection.ops.drop_foreignkey_sql` |
| `backend.get_fulltext_search_sql` | `connection.ops.fulltext_search_sql` |
| `backend.get_last_insert_id` | `connection.ops.last_insert_id` |
| `backend.get_limit_offset_sql` | `connection.ops.limit_offset_sql` |
| `backend.get_max_name_length` | `connection.ops.max_name_length` |
| `backend.get_pk_default_value` | `connection.ops.pk_default_value` |
| `backend.get_random_function_sql` | `connection.ops.random_function_sql` |
| `backend.get_sql_flush` | `connection.ops.sql_flush` |
| `backend.get_sql_sequence_reset` | `connection.ops.sequence_reset_sql` |
| `backend.get_start_transaction_sql` | `connection.ops.start_transaction_sql` |
| `backend.get_tablespace_sql` | `connection.ops.tablespace_sql` |
| `backend.quote_name` | `connection.ops.quote_name` |
| `backend.get_query_set_class` | `connection.ops.query_set_class` |
| `backend.get_field_cast_sql` | `connection.ops.field_cast_sql` |
| `backend.get_drop_sequence` | `connection.ops.drop_sequence_sql` |
| `backend.OPERATOR_MAPPING` | `connection.operators` |
| `backend.allows_group_by_ordinal` | `connection.features.allows_group_by_ordinal` |
| `backend.allows_unique_and_pk` | `connection.features.allows_unique_and_pk` |
| `backend.autoindexes_primary_keys` | `connection.features.autoindexes_primary_keys` |
| `backend.needs_datetime_string_cast` | `connection.features.needs_datetime_string_cast` |
| `backend.needs_upper_for_iops` | `connection.features.needs_upper_for_iops` |
| `backend.supports_constraints` | `connection.features.supports_constraints` |
| `backend.supports_tablespaces` | `connection.features.supports_tablespaces` |
| `backend.uses_case_insensitive_names` | `connection.features.uses_case_insensitive_names` |
| `backend.uses_custom_queryset` | `connection.features.uses_custom_queryset` |
