Метод extra
Метод extra применяется к QuerySet и позволяет вставлять пользовательские SQL-выражения в различные части запроса. Он предоставляет гибкость для выполнения сложных операций, таких как пользовательские сортировки, вычисляемые поля или фильтрация с использованием специфичных для базы данных функций. Важно отметить, что метод extra считается устаревшим и рекомендуется использовать другие подходы, например, аннотации с функциями баз данных, но он все еще полезен для миграции старого кода.
Синтаксис
Model.objects.extra(select=None, where=None, params=None, tables=None, order_by=None, select_params=None)
Метод принимает следующие параметры:
-
select- словарь псевдонимов и SQL-выражений для добавления в раздел SELECT -
where- список строк с условиями для добавления в раздел WHERE -
params- список параметров для безопасной подстановки в условия WHERE -
tables- список таблиц для добавления в раздел FROM -
order_by- список выражений для сортировки результатов -
select_params- список параметров для подстановки в выражения SELECT
Пример
Добавим вычисляемое поле с возрастом пользователя на основе даты рождения:
from 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}")
Результат выполнения кода:
"john_doe: 28"
"jane_smith: 34"
"bob_johnson: 45"
Пример
Отфильтруем пользователей, у которых возраст больше 30 лет, используя пользовательское условие WHERE:
from 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)
Результат выполнения кода:
"jane_smith"
"bob_johnson"
Пример
Отсортируем статьи по длине заголовка с использованием SQL-функции LENGTH:
from myapp.models import Article
articles = Article.objects.extra(
order_by=["LENGTH(title)"]
)
for article in articles:
print(f"{article.title} - {len(article.title)} chars")
Результат выполнения кода:
"Article - 7 chars"
"Longer Title Here - 16 chars"
"The Longest Title Example - 24 chars"
Пример
Используем несколько таблиц для сложного запроса:
from 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 Basics - Programming"
"Web Development - Programming"
"Data Science - Technology"
Пример
Используем параметры в SELECT выражении с безопасной подстановкой:
from 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}")
Результат выполнения кода:
"Product A: 120.0"
"Product B: 180.0"
"Product C: 240.0"