Класс Func

Класс Func из модуля django.db.models представляет собой базовый класс для создания SQL-функций в Django ORM. Он позволяет выполнять произвольные SQL-функции прямо в запросах, преобразовывать данные, выполнять вычисления и агрегации на уровне базы данных. Класс принимает аргументы в виде позиционных или именованных параметров, которые передаются в SQL-функцию.

Синтаксис

pythonfrom django.db.models import Func

class CustomFunction(Func):
  function = 'SQL_FUNCTION_NAME'
  template = '%(function)s(%(expressions)s)'

Параметры класса

Основные атрибуты класса Func:

Пример . С функцией LENGTH

Рассмотрим пример использования встроенной SQL-функции LENGTH для подсчета длины строки:

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

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

python{"title": "Hello World", "title_length": 11}
{"title": "Django ORM", "title_length": 10}

Пример . С пользовательской функцией

Создадим собственный класс для работы с функцией CONCAT:

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

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

python{"full_name": "John Doe"}
{"full_name": "Jane Smith"}

Пример . С функцией COALESCE

Используем функцию COALESCE для подстановки значения по умолчанию, если поле равно NULL:

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

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

python{"display_name": "Laptop"}
{"display_name": "Unnamed Product"}

Пример . С вызовом собственной SQL-функции

Создадим пользовательский класс для вызова хранимой функции GET_TAX:

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

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

python{"id": 1, "tax_amount": 20.0}
{"id": 2, "tax_amount": 15.5}

Пример . С использованием аргументов

Используем класс Func с позиционными и именованными аргументами:

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

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

python{"discount": 50.0}
{"discount": 30.0}

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

  • класс F,
    который позволяет ссылаться на поля модели в выражениях
  • класс Concat,
    который объединяет строки в SQL-запросе
  • класс Coalesce,
    который возвращает первое не-NULL значение
  • класс Cast,
    который преобразует типы данных в SQL-запросе