Модели практикума
В практикуме используется приложение management_app с пятью моделями:
- Tag — тэг задачи (name)
- Project — проект (name, description, date_of_creation)
- ProjectFile — файл проекта (file_name, file_path, created_at); M2M к Project через
project_files - User — стандартная модель Django
django.contrib.auth.models.User - Task — задача (name, status, priority, due_date, created_date, assignee→User, project→Project, tags M2M→Tag)
Django shell
Django shell — это интерактивная Python-консоль, в которой уже настроено окружение Django: можно сразу импортировать модели и делать ORM-запросы.
python manage.py shell
После запуска появляется стандартный Python REPL с доступом ко всем приложениям проекта.
QuerySet API — ключевые методы
Создание объектов
# Вариант 1: create + save
obj = MyModel(field='value')
obj.save()
# Вариант 2: objects.create (сразу сохраняет в БД)
obj = MyModel.objects.create(field='value')
Чтение
MyModel.objects.all() # все записи
MyModel.objects.first() # первая
MyModel.objects.last() # последняя
MyModel.objects.count() # количество
MyModel.objects.filter(k=v) # фильтр по условию
MyModel.objects.exclude(k=v) # исключить по условию
MyModel.objects.filter(k=v).exists() # True/False
Lookups (поиск по полям)
Model.objects.filter(name__icontains='text') # содержит (без учёта регистра)
Model.objects.filter(date__gt=value) # строго больше
Model.objects.filter(date__gte=value) # больше или равно
Model.objects.filter(date__lte=value) # меньше или равно
Model.objects.filter(date__month=F('...') + 1) # по месяцу
Model.objects.filter(field__isnull=True) # NULL
Model.objects.filter(related__name='value') # через связь (JOIN)
Q-класс — комбинированные условия
Q-класс позволяет строить сложные условия с логическими операторами:
from django.db.models import Q
# AND
Model.objects.filter(Q(status='new') & Q(priority='Urgent'))
# OR
Model.objects.filter(Q(status='new') | Q(priority='Critical'))
# NOT
Model.objects.filter(~Q(tags__name='Q&A'))
# Комбинация
Model.objects.filter(
(Q(status='new') & Q(priority='Urgent')) | ~Q(tags__name='Q&A')
)
F-класс — ссылка на значение поля
F-класс позволяет обращаться к значению поля на стороне БД — без загрузки объекта в Python. Это эффективно при массовых обновлениях.
from django.db.models import F
from datetime import timedelta
# Увеличить due_date на 7 дней для всех задач
Task.objects.update(due_date=F('due_date') + timedelta(weeks=1))
# Фильтрация: задачи, чей due_date приходится на следующий месяц после создания
Task.objects.filter(due_date__month=F('created_date__month') + 1)
Обновление
# Обновить через QuerySet (один SQL UPDATE)
Task.objects.filter(name='Update schema').update(status='pending')
# Массовое обновление через bulk_update
tasks = Task.objects.filter(status='new')
for task in tasks:
task.status = 'in_progress'
Task.objects.bulk_update(tasks, ['status'])
bulk_update vs update()
.update() выполняет один SQL UPDATE с WHERE — быстро, но не вызывает сигналы и save().bulk_update() вызывает один SQL-запрос по списку объектов — подходит когда значения разные для каждого объекта.
Агрегация и аннотация
from django.db.models import Count
# Аннотировать каждый проект количеством файлов
Project.objects.annotate(file_count=Count('project_files'))
# Фильтровать по аннотированному полю
Project.objects.annotate(
file_count=Count('project_files')
).filter(file_count__gte=3)
ManyToMany — добавление связей
# Добавить тэг к задаче
task.tags.add(tag_object)
# Добавить файл к проекту
project.project_files.add(file_object)