django 3.1 передача псевдонимов необработанных столбцов в QuerySet.order_by() устарела

#django #django-queryset #deprecated #django-3.1

Вопрос:

Я работаю над проектом, который только что перешел на django 3.1. И мне нужно удалить использование этой «передачи псевдонимов необработанных столбцов в QuerySet.order_by ()». Однако я не уверен, использует ли его мой проект. Поэтому мне нужно понять, как на самом деле работает «передача псевдонимов необработанных столбцов в QuerySet.order_by ()», если бы кто-нибудь мог предоставить мне пример кода, который передает псевдонимы необработанных столбцов в QuerySet.order_by (), это было бы действительно полезно и ценно.

Ответ №1:

tl;dr:

  • запросы, которые используют синтаксис с разделителями точек для ссылок на таблицы и столбцы, следует изменить
  • запросы, в которых используются __ ссылки с разделителями на таблицы и столбцы, хороши как есть

Обнаружение устаревших версий во время выполнения

Ну, во-первых, самый простой способ обнаружить использование устаревших шаблонов-это запустить свой проект и/или набор тестов с 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')
 

Пример — исправление неправильного запроса

Рассмотрим ниже — есть два запроса, каждый из которых будет упорядочивать учителей по срокам службы:

 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()
)
 

Эти два запроса эквивалентны и переводятся на (сокращенный) SQL:

 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
 

Пример — незатронутые запросы

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

Эти запросы просто прекрасны, и их не нужно изменять:

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

# Safe - we're ordering by `auth_user.date_joined`
User.objects.order_by('date_joined')

# Safe - we're ordering by `auth_group.name` after a JOIN on auth_group
User.objects.order_by('groups__name')