💻 Примеры: ORM-запросы в Django

Показательные примеры по теме практикума

⚡ Ключевые паттерны

# Q-класс: OR + NOT
Task.objects.filter(Q(priority='Urgent') | ~Q(tags__name='Q&A'))

# F-класс: сдвиг даты
Task.objects.update(due_date=F('due_date') + timedelta(weeks=1))

# bulk_update
tasks = Task.objects.filter(status='new')
for t in tasks: t.status = 'in_progress'
Task.objects.bulk_update(tasks, ['status'])

# annotate + filter
Project.objects.annotate(
    cnt=Count('project_files')
).filter(cnt__gte=3)

← К оглавлению урока

Пример 1: Создание объектов через save() и create()

from management_app.models.tag import Tag
from management_app.models.project import Project

# Способ 1: создать объект, затем save()
backend_tag = Tag(name='Backend')
backend_tag.save()

# Способ 2: objects.create() — атомарно (без отдельного .save())
frontend_tag = Tag.objects.create(name='Frontend')

# Создание проекта
tiger = Project(name='TIGER', description='First project')
tiger.save()

saphyr = Project.objects.create(name='SapHYR INC', description='Best project')

Пример 2: ManyToMany — добавление тэгов к задачам

# После создания задачи добавляем тэги через related manager
task.tags.add(backend_tag)

# Несколько тэгов сразу
task.tags.add(backend_tag, qa_tag)

Пример 3: Фильтрация с lookups

from django.utils import timezone

# Теги, содержащие 'e' (без учёта регистра)
Tag.objects.filter(name__icontains='e')
# Результат: [Backend, Design, DevOPS, Frontend]

# Проверить наличие тэга
Tag.objects.filter(name='SUPERTAG').exists()
# Результат: False

# Проекты старше определённой даты
req_date = timezone.datetime(2023, 1, 1).astimezone()
Project.objects.filter(date_of_creation__gt=req_date)

Пример 4: Q-класс — комбинированные условия

from django.db.models import Q

# AND: дата И имя
Project.objects.filter(
    Q(date_of_creation__gt=req_date) & Q(name__icontains='TI')
)
# Результат: [TIGER]

# OR + NOT: статус+приоритет ИЛИ НЕ тэг Q&A
Task.objects.filter(
    (Q(status='new') & Q(priority='Urgent')) | ~Q(tags__name='Q&A')
)

Пример 5: F-класс — обновление через значение поля

from django.db.models import F
from datetime import timedelta

# Увеличить due_date на неделю для всех задач
Task.objects.update(due_date=F('due_date') + timedelta(weeks=1))

# Фильтр: задачи, у которых due_date в следующем месяце после created_date
Task.objects.filter(
    due_date__month=F('created_date__month') + 1
).update(priority='Critical')

Пример 6: bulk_update — массовое обновление

from datetime import timedelta
from django.db.models import F

# Получаем все задачи со статусом 'new'
tasks_to_update = Task.objects.filter(status='new')

# Меняем статус для каждого объекта в Python
for task in tasks_to_update:
    task.status = 'in_progress'

# Один SQL-запрос для всех объектов
Task.objects.bulk_update(tasks_to_update, ['status'])

# bulk_update с F-классом: сдвиг due_date на 3 дня
tasks = Task.objects.filter(status='in_progress')
for task in tasks:
    task.due_date = F('due_date') + timedelta(days=3)
Task.objects.bulk_update(tasks, ['due_date'])

Пример 7: annotate(Count) — фильтрация по связям

from django.db.models import Count, Q
from django.utils import timezone

req_date = timezone.datetime(2023, 7, 7).astimezone()

# Проекты с датой > req_date и количеством файлов >= 3
projects_filtered = Project.objects.annotate(
    file_count=Count('project_files')
).filter(
    Q(date_of_creation__gt=req_date) & Q(file_count__gte=3)
)

Пример 8: Получение проектов через связанные файлы

import datetime
from django.utils import timezone
from management_app.models.project import Project, ProjectFile

last_week = timezone.now() - datetime.timedelta(days=7)

# Файлы, созданные за последнюю неделю
recent_files = ProjectFile.objects.filter(created_at__gte=last_week)

# Проекты, у которых есть эти файлы
projects_with_recent_files = Project.objects.filter(
    project_files__in=recent_files
).distinct()

Пример 9: exclude() — исключение по Q

from django.db.models import Q

# Все задачи, кроме 'pending' и 'closed'
tasks_excluded = Task.objects.exclude(
    Q(status='pending') | Q(status='closed')
)

Пример 10: Функция вычисления конца месяца

from django.utils import timezone
import calendar

def calculate_end_of_month():
    current_date = timezone.now()
    amount_of_days = calendar.monthrange(
        current_date.year,
        current_date.month
    )[1]
    # Используем datetime Django для timezone-aware объекта
    from django.utils.timezone import make_aware
    import datetime
    date = datetime.datetime(
        year=current_date.year,
        month=current_date.month,
        day=amount_of_days,
    )
    return make_aware(date)

end_of_month = calculate_end_of_month()

tasks_filtered = Task.objects.filter(
    Q(priority='High') | Q(priority='Critical'),
    due_date__lte=end_of_month
)
⚠️ Проверить по документации: from django.db.models.functions.datetime import datetime — нестандартный импорт из источника лекции. Рекомендуется использовать стандартный import datetime и django.utils.timezone.make_aware() для timezone-aware дат.

← К оглавлению урока