Класс Concat

Класс Concat применяется в сочетании с методом annotate для создания нового поля, содержащего результат объединения нескольких выражений. В качестве аргументов конструктор принимает одно или несколько выражений (поля моделей, строковые литералы или объекты Value). Также можно передать именованный параметр output_field для явного указания типа поля результата. Объединение выполняется в том порядке, в котором переданы аргументы.

Синтаксис

pythonfrom django.db.models import Concat, Value, F
from django.db.models.functions import Concat

# Базовое использование
Concat(expression1, expression2, ..., output_field=CharField())

# Использование с F и Value
Concat(F('first_name'), Value(' '), F('last_name'))

# В annotate
Model.objects.annotate(full_name=Concat(...))

Пример

Объединим имя и фамилию пользователя с пробелом между ними:

pythonfrom django.db.models import Concat, Value, F
from django.db.models.functions import Concat
from myapp.models import User

# Получаем пользователей с полным именем
users = User.objects.annotate(
  full_name=Concat('first_name', Value(' '), 'last_name')
)

for user in users:
  print(user.full_name)

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

python"John Doe"
"Jane Smith"
"Bob Johnson"

Пример

Объединим несколько полей статьи в одно строковое представление:

pythonfrom django.db.models import Concat, Value, F
from django.db.models.functions import Concat
from myapp.models import Article

# Создаем строку "title (author) - created_at"
articles = Article.objects.annotate(
  info=Concat(
    'title',
    Value(' ('),
    'author',
    Value(') - '),
    'created_at'
  )
)

for article in articles:
  print(article.info)

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

python"Django Basics (John) - 2025-01-15 10:30:00"
"Python Tips (Jane) - 2025-01-20 14:45:00"

Пример

Используем Concat с условным объединением с помощью Case:

pythonfrom django.db.models import Concat, Value, F, Case, When, Q
from django.db.models.functions import Concat
from myapp.models import Product

# Создаем описание продукта с учетом наличия скидки
products = Product.objects.annotate(
  description=Case(
    When(
      Q(discount__gt=0),
      then=Concat(
        'name',
        Value(' (Скидка '),
        'discount',
        Value('%)')
      )
    ),
    default=Concat('name', Value(' (Без скидки)')),
    output_field=CharField()
  )
)

for product in products:
  print(product.description)

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

python"Laptop (Скидка 15%)"
"Smartphone (Скидка 10%)"
"Headphones (Без скидки)"

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

  • класс Value,
    который используется для передачи строковых литералов в запрос
  • класс F,
    который ссылается на значение поля модели
  • класс Case,
    который позволяет создавать условные выражения
  • функция annotate,
    которая добавляет аннотированные поля к QuerySet