Класс Trunc
Класс Trunc из модуля django.db.models.functions
применяется для усечения значений даты и времени до заданной
точности. Он позволяет округлить дату до года, месяца, дня,
часа, минуты или секунды. Класс особенно полезен при
группировке записей по временным интервалам в аннотациях
и агрегациях.
Основные аргументы конструктора Trunc:
-
expression- поле модели или выражение, содержащее дату и время для усечения -
kind- строка, определяющая единицу усечения:'year','month','day','hour','minute','second' -
tzinfo- опциональный часовой пояс для усечения
Синтаксис
from django.db.models.functions import Trunc
Model.objects.annotate(
truncated_field=Trunc('field_name', kind='day')
)
Пример
Рассмотрим модель Article с полем
created_at типа DateTimeField.
Сгруппируем статьи по дням и подсчитаем количество
записей за каждый день:
from django.db.models import Count
from django.db.models.functions import Trunc
from myapp.models import Article
# Группировка по дням
articles_by_day = (
Article.objects
.annotate(day=Trunc('created_at', kind='day'))
.values('day')
.annotate(count=Count('id'))
.order_by('day')
)
for entry in articles_by_day:
print(f"{entry['day']}: {entry['count']} articles")
Результат выполнения кода:
"2025-01-01 00:00:00+00:00: 5 articles"
"2025-01-02 00:00:00+00:00: 3 articles"
"2025-01-03 00:00:00+00:00: 8 articles"
Пример
Сгруппируем записи по месяцам и подсчитаем общее количество комментариев за каждый месяц:
from django.db.models import Sum
from django.db.models.functions import Trunc
from myapp.models import Comment
# Группировка по месяцам
comments_by_month = (
Comment.objects
.annotate(month=Trunc('created_at', kind='month'))
.values('month')
.annotate(total=Sum('count'))
.order_by('month')
)
for entry in comments_by_month:
print(f"{entry['month']}: {entry['total']} comments")
Результат выполнения кода:
"2025-01-01 00:00:00+00:00: 150 comments"
"2025-02-01 00:00:00+00:00: 210 comments"
"2025-03-01 00:00:00+00:00: 180 comments"
Пример
Используем усечение до часа для анализа активности пользователей в течение дня:
from django.db.models import Count
from django.db.models.functions import Trunc
from myapp.models import UserAction
# Группировка по часам
actions_by_hour = (
UserAction.objects
.annotate(hour=Trunc('timestamp', kind='hour'))
.values('hour')
.annotate(actions=Count('id'))
.order_by('hour')
)
for entry in actions_by_hour:
print(f"{entry['hour']}: {entry['actions']} actions")
Результат выполнения кода:
"2025-01-15 08:00:00+00:00: 45 actions"
"2025-01-15 09:00:00+00:00: 67 actions"
"2025-01-15 10:00:00+00:00: 89 actions"