Метод extra

Метод extra применяется к QuerySet и позволяет вставлять пользовательские SQL-выражения в различные части запроса. Он предоставляет гибкость для выполнения сложных операций, таких как пользовательские сортировки, вычисляемые поля или фильтрация с использованием специфичных для базы данных функций. Важно отметить, что метод extra считается устаревшим и рекомендуется использовать другие подходы, например, аннотации с функциями баз данных, но он все еще полезен для миграции старого кода.

Синтаксис

pythonModel.objects.extra(select=None, where=None, params=None, tables=None, order_by=None, select_params=None)

Метод принимает следующие параметры:

Пример

Добавим вычисляемое поле с возрастом пользователя на основе даты рождения:

pythonfrom myapp.models import User
from datetime import date

age_users = User.objects.extra(
  select={
    'age': "EXTRACT(YEAR FROM AGE(CURRENT_DATE, birth_date))"
  }
)
for user in age_users:
  print(f"{user.username}: {user.age}")

Результат выполнения кода:

python"john_doe: 28"
"jane_smith: 34"
"bob_johnson: 45"

Пример

Отфильтруем пользователей, у которых возраст больше 30 лет, используя пользовательское условие WHERE:

pythonfrom myapp.models import User

users = User.objects.extra(
  where=["EXTRACT(YEAR FROM AGE(CURRENT_DATE, birth_date)) > %s"],
  params=[30]
)
for user in users:
  print(user.username)

Результат выполнения кода:

python"jane_smith"
"bob_johnson"

Пример

Отсортируем статьи по длине заголовка с использованием SQL-функции LENGTH:

pythonfrom myapp.models import Article

articles = Article.objects.extra(
  order_by=["LENGTH(title)"]
)
for article in articles:
  print(f"{article.title} - {len(article.title)} chars")

Результат выполнения кода:

python"Article - 7 chars"
"Longer Title Here - 16 chars"
"The Longest Title Example - 24 chars"

Пример

Используем несколько таблиц для сложного запроса:

pythonfrom myapp.models import Article, Category

articles = Article.objects.extra(
  tables=["myapp_category"],
  where=["myapp_article.category_id = myapp_category.id"],
  select={"category_name": "myapp_category.name"}
)
for article in articles:
  print(f"{article.title} - {article.category_name}")

Результат выполнения кода:

python"Python Basics - Programming"
"Web Development - Programming"
"Data Science - Technology"

Пример

Используем параметры в SELECT выражении с безопасной подстановкой:

pythonfrom myapp.models import Product

products = Product.objects.extra(
  select={
    'price_with_tax': "price * %s"
  },
  select_params=[1.2]
)
for product in products:
  print(f"{product.name}: {product.price_with_tax}")

Результат выполнения кода:

python"Product A: 120.0"
"Product B: 180.0"
"Product C: 240.0"

Смотрите также

  • метод annotate,
    который добавляет вычисляемые поля через агрегатные функции
  • метод filter,
    который фильтрует QuerySet на основе заданных условий
  • метод order_by,
    который сортирует QuerySet по указанным полям
  • метод values,
    который возвращает QuerySet словарей вместо объектов