Класс Func
Класс Func из модуля django.db.models представляет собой базовый класс для создания SQL-функций в Django ORM. Он позволяет выполнять произвольные SQL-функции прямо в запросах, преобразовывать данные, выполнять вычисления и агрегации на уровне базы данных. Класс принимает аргументы в виде позиционных или именованных параметров, которые передаются в SQL-функцию.
Синтаксис
from django.db.models import Func
class CustomFunction(Func):
function = 'SQL_FUNCTION_NAME'
template = '%(function)s(%(expressions)s)'
Параметры класса
Основные атрибуты класса Func:
- function - имя SQL-функции (обязательный атрибут);
- template - шаблон для генерации SQL (по умолчанию '%(function)s(%(expressions)s)');
- arg_joiner - разделитель между аргументами (по умолчанию ', ');
- arity - количество аргументов (если ограничено).
Пример . С функцией LENGTH
Рассмотрим пример использования встроенной SQL-функции LENGTH для подсчета длины строки:
from django.db.models import Func
from myapp.models import Article
articles = Article.objects.annotate(
title_length=Func('title', function='LENGTH')
).values('title', 'title_length')
for article in articles:
print(article)
Результат выполнения кода:
{"title": "Hello World", "title_length": 11}
{"title": "Django ORM", "title_length": 10}
Пример . С пользовательской функцией
Создадим собственный класс для работы с функцией CONCAT:
from django.db.models import Func, Value
from myapp.models import User
class Concat(Func):
function = 'CONCAT'
template = '%(function)s(%(expressions)s)'
users = User.objects.annotate(
full_name=Concat('first_name', Value(' '), 'last_name')
).values('full_name')
for user in users:
print(user)
Результат выполнения кода:
{"full_name": "John Doe"}
{"full_name": "Jane Smith"}
Пример . С функцией COALESCE
Используем функцию COALESCE для подстановки значения по умолчанию, если поле равно NULL:
from django.db.models import Func, Value
from myapp.models import Product
products = Product.objects.annotate(
display_name=Func(
'name',
Value('Unnamed Product'),
function='COALESCE',
template='%(function)s(%(expressions)s)'
)
).values('display_name')
for product in products:
print(product)
Результат выполнения кода:
{"display_name": "Laptop"}
{"display_name": "Unnamed Product"}
Пример . С вызовом собственной SQL-функции
Создадим пользовательский класс для вызова хранимой функции GET_TAX:
from django.db.models import Func
from myapp.models import Order
class GetTax(Func):
function = 'GET_TAX'
template = '%(function)s(%(expressions)s)'
orders = Order.objects.annotate(
tax_amount=GetTax('price', 'country_code')
).values('id', 'tax_amount')
for order in orders:
print(order)
Результат выполнения кода:
{"id": 1, "tax_amount": 20.0}
{"id": 2, "tax_amount": 15.5}
Пример . С использованием аргументов
Используем класс Func с позиционными и именованными аргументами:
from django.db.models import Func, Value
from myapp.models import Order
orders = Order.objects.annotate(
discount=Func(
Value('DISCOUNT'),
'amount',
Value(10),
function='APPLY_DISCOUNT',
template='%(function)s(%(expressions)s)',
)
).values('discount')
for order in orders:
print(order)
Результат выполнения кода:
{"discount": 50.0}
{"discount": 30.0}