django 3.1 不推荐将原始列别名传递给 QuerySet.order_by()

Unk*_*own 4 django deprecated django-queryset django-3.1

我正在开发一个刚刚迁移到 django 3.1 的项目。我需要删除“将原始列别名传递给 QuerySet.order_by()”的用法。但是,我不确定我的项目是否正在使用它。所以我需要了解“将原始列别名传递给 QuerySet.order_by()”实际上是如何工作的,如果有人可以为我提供一个将原始列别名传递给 QuerySet.order_by() 的代码示例,那真的是有帮助并表示赞赏。

Dav*_*ain 6

长话短说:

  • 应更改使用点分隔语法来引用表和列的查询
  • 使用__对表和列的分隔引用的查询按原样就可以了

运行时检测弃用

好吧,首先检测已弃用模式的使用的最简单方法是使用 或 运行您的项目和/或测试PYTHONWARNINGS=always套件python -Wd。如果这样做,您将看到一些有用的警告,可以突出显示不良模式所在的确切行。

例如,当您使用 Django 3.1 运行我的示例代码时会引发警告:

RemovedInDjango40Warning: Passing column raw column aliases to order_by() is deprecated. Wrap '-auth_user_groups.id' in a RawSQL expression before passing it to order_by().
  User.objects.filter(groups__name='teachers').order_by('-auth_user_groups.id')
Run Code Online (Sandbox Code Playgroud)

示例 - 修复错误查询

考虑以下情况 - 有两个查询,每个查询都会按任期对教师进行排序:

RemovedInDjango40Warning: Passing column raw column aliases to order_by() is deprecated. Wrap '-auth_user_groups.id' in a RawSQL expression before passing it to order_by().
  User.objects.filter(groups__name='teachers').order_by('-auth_user_groups.id')
Run Code Online (Sandbox Code Playgroud)

这两个查询是等效的,并转换为(缩写的)SQL:

from django.contrib.auth.models import User
from django.db.models.expressions import RawSQL

# Deprecated!
# The value passed to `order_by` references a column on a table
User.objects.filter(groups__name='teachers').order_by('-auth_user_groups.id')

# Safe! We're now using RawSQL to make that same reference.
User.objects.filter(groups__name='teachers').order_by(
    RawSQL('auth_user_groups.id', tuple()).desc()
)
Run Code Online (Sandbox Code Playgroud)

示例 - 不受影响的查询

不过,大多数查询不会使用点分隔语法引用表名和列。

这些查询很好,不需要更改:

SELECT auth_user.*
  FROM auth_user
 INNER JOIN auth_user_groups ON auth_user.id = auth_user_groups.user_id
 INNER JOIN auth_group ON auth_user_groups.group_id = auth_group.id
 WHERE auth_group.name = 'teachers'
 ORDER BY auth_user_groups.id DESC
Run Code Online (Sandbox Code Playgroud)