← Назад к вопросам
Чем пользовался для оптимизации запросов в Django?
1.8 Middle🔥 151 комментариев
#Django#Базы данных (SQL)
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Чем пользовался для оптимизации запросов в Django
Django предоставляет мощный набор инструментов для оптимизации запросов к БД. Это критически важно для производительности приложений.
1. select_related() — для ForeignKey и OneToOne
class Post(models.Model):
title = models.CharField(max_length=200)
author = models.ForeignKey('User', on_delete=models.CASCADE)
class Comment(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE)
user = models.ForeignKey('User', on_delete=models.CASCADE)
# Проблема: N+1 SELECT
comments = Comment.objects.all()
for comment in comments:
print(comment.post.title) # Новый SELECT для каждого!
# Решение: select_related()
comments = Comment.objects.select_related('post', 'user').all()
for comment in comments:
print(comment.post.title) # Уже в памяти!
2. prefetch_related() — для ManyToMany и reverse ForeignKey
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
title = models.CharField(max_length=200)
authors = models.ManyToManyField(Author)
# Проблема: N+1 SELECT
books = Book.objects.all()
for book in books:
authors = book.authors.all() # Новый SELECT!
# Решение: prefetch_related()
books = Book.objects.prefetch_related('authors').all()
for book in books:
authors = book.authors.all() # Кешировано!
3. only() и defer() — выбрать нужные колонки
# Загружаем ВСЕ
users = User.objects.all()
# Только нужное
users = User.objects.only('id', 'username', 'email')
# Исключаем ненужное
users = User.objects.defer('bio', 'large_text')
4. Annotate() — агрегация в БД
from django.db.models import Count, Sum, Avg
# Проблема: отдельный COUNT для каждого юзера
for user in User.objects.all():
post_count = user.posts.count()
# Решение: аннотация
users = User.objects.annotate(
post_count=Count('posts'),
total_views=Sum('posts__views'),
avg_likes=Avg('posts__likes')
).filter(post_count__gte=5)
5. values() и values_list()
# Полные объекты
users = User.objects.all()
# Словари
users = User.objects.values('id', 'username', 'email')
# Кортежи
users = User.objects.values_list('id', 'username')
for user_id, username in users:
print(f"{user_id}: {username}")
6. exists() вместо count()
# Медленно: считает ВСЕ
if User.objects.filter(email='test@example.com').count() > 0:
...
# Быстро: останавливается после первой
if User.objects.filter(email='test@example.com').exists():
...
7. bulk_create() и bulk_update()
# Медленно: 1000 INSERT запросов
users = [User(username=f'user{i}') for i in range(1000)]
for user in users:
user.save()
# Быстро: несколько запросов
User.objects.bulk_create(users, batch_size=500)
# Обновление
User.objects.bulk_update(users, fields=['last_login'], batch_size=500)
8. Django Debug Toolbar
# settings.py
INSTALLED_APPS = ['debug_toolbar', ...]
MIDDLEWARE = ['debug_toolbar.middleware.DebugToolbarMiddleware', ...]
INTERNAL_IPS = ['127.0.0.1']
# urls.py
if DEBUG:
import debug_toolbar
urlpatterns += [path('__debug__/', include(debug_toolbar.urls))]
# В браузере видите все SQL запросы и время выполнения
9. QuerySet.explain()
users = User.objects.all()
print(users.query.explain(verbose=True))
# Показывает EXPLAIN ANALYZE из БД
10. Полный пример оптимизации
from django.db.models import Count, Prefetch
class BlogListView(ListView):
model = Post
def get_queryset(self):
return Post.objects.select_related(
'author',
'category'
).prefetch_related(
'tags',
Prefetch('comments', queryset=Comment.objects.select_related('author'))
).only(
'id', 'title', 'published_at',
'author__id', 'author__username',
'category__name'
).annotate(
comment_count=Count('comments'),
tag_count=Count('tags')
).filter(
published=True,
comment_count__gte=1
).order_by('-published_at')
Чеклист оптимизации
- select_related() для ForeignKey / OneToOne
- prefetch_related() для ManyToMany / reverse FK
- only() / defer() для нужных колонок
- annotate() для агрегации в БД
- values() / values_list() для словарей/кортежей
- exists() вместо count() для проверки
- bulk_create() / bulk_update() для пакетов
- Debug Toolbar для профилирования
- explain() для анализа плана
- Тестировать с реальным объёмом данных!
Оптимизация запросов в Django — систематический подход, начиная с профилирования и заканчивая применением инструментов кеширования.