← Назад к вопросам

Какие используешь библиотеки для оптимизации в Django?

1.8 Middle🔥 191 комментариев
#Django

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Какие используешь библиотеки для оптимизации в Django?

Оптимизация Django-приложения — это критически важный аспект production-разработки. Вот библиотеки, которые я использую регулярно.

1. Django Debug Toolbar

Для чего: Анализ SQL запросов, профилирование, отладка.

# settings.py
INSTALLED_APPS = [
    'debug_toolbar',
    # ...
]

MIDDLEWARE = [
    'debug_toolbar.middleware.DebugToolbarMiddleware',
    # ...
]

INTERNAL_IPS = ['127.0.0.1']
# urls.py
if settings.DEBUG:
    urlpatterns += [
        path('__debug__/', include('debug_toolbar.urls')),
    ]

Что показывает:

  • Количество SQL запросов
  • Дублирующиеся запросы (N+1 проблема)
  • Время выполнения
  • Кэширование и middleware

2. Django Silk

Для чего: Profiling HTTP запросов в production (с осторожностью).

# settings.py
INSTALLED_APPS = [
    'silk',
]

MIDDLEWARE = [
    'silk.middleware.SilkyMiddleware',
]

SILKY_PYTHON_PROFILER = True
SILKY_IGNORE_PATTERNS = [r'^/static/', r'^/media/']

Возможности:

  • История всех HTTP запросов
  • Профилирование кода
  • SQL запросы
  • Визуальная диаграмма вызовов

3. django-extensions

Для чего: Утилиты для анализа и отладки.

# Использование
python manage.py shell_plus  # Автоимпорт моделей
python manage.py runprofileserver  # С профилированием
python manage.py show_urls  # Список всех URL
python manage.py graph_models -a -o myapp.png  # Граф моделей

# Для каждого эндпоинта показывает:
# - Время выполнения
# - CPU usage
# - Кумулятивное время

4. django-cachalot

Для чего: Автоматическое кэширование ORM запросов.

# settings.py
INSTALLED_APPS = [
    'cachalot',
]

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.redis.RedisCache',
        'LOCATION': 'redis://127.0.0.1:6379/1',
    }
}
# Работает автоматически
from myapp.models import User

# Первый вызов — из БД
users = User.objects.all()  # SQL запрос

# Второй вызов — из кэша
users = User.objects.all()  # Из Redis, быстрее

# При изменении таблицы кэш инвалидируется автоматически
user = User.objects.create(name='John')  # Кэш очищен

# Отключение кэша для критичных запросов
from cachalot.api import cachalot

with cachalot.disabled():
    users = User.objects.all()  # Всегда из БД

5. django-redis

Для чего: Интеграция Redis для кэширования и сессий.

# settings.py
CACHES = {
    'default': {
        'BACKEND': 'django_redis.cache.RedisCache',
        'LOCATION': 'redis://127.0.0.1:6379/1',
        'OPTIONS': {
            'CLIENT_CLASS': 'django_redis.client.DefaultClient',
            'CONNECTION_POOL_KWARGS': {
                'max_connections': 50,
                'retry_on_timeout': True,
            },
            'SOCKET_CONNECT_TIMEOUT': 5,
            'SOCKET_TIMEOUT': 5,
        }
    }
}

SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
SESSION_CACHE_ALIAS = 'default'
# Использование
from django.core.cache import cache

# Кэширование результата
user_data = cache.get('user_123')
if user_data is None:
    user_data = User.objects.get(id=123)
    cache.set('user_123', user_data, timeout=3600)

# Или декоратор
from django.views.decorators.cache import cache_page

@cache_page(60 * 15)  # 15 минут
def expensive_view(request):
    # Долгие вычисления
    return render(request, 'template.html')

6. select_related и prefetch_related

Для чего: Решение N+1 проблемы.

from django.db.models import Prefetch

# ❌ Плохо — N+1 проблема
users = User.objects.all()
for user in users:
    print(user.profile.bio)  # На каждого user идёт отдельный запрос

# ✅ Хорошо — select_related для ForeignKey
users = User.objects.select_related('profile').all()
# SQL: SELECT * FROM user JOIN profile ON ...

# ✅ Для ManyToMany — prefetch_related
posts = Post.objects.prefetch_related('comments').all()
# SQL: SELECT * FROM post; SELECT * FROM comment WHERE post_id IN (...)

# Комбинирование
posts = Post.objects.select_related('author').prefetch_related('comments').all()

# Кастомный prefetch
from django.db.models import Prefetch

comments = Comment.objects.filter(approved=True)
posts = Post.objects.prefetch_related(
    Prefetch('comments', queryset=comments)
).all()

7. django-rest-framework с оптимизацией

Для чего: Эффективные REST API.

from rest_framework import serializers, viewsets
from rest_framework.pagination import PageNumberPagination

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ['id', 'name', 'email']

class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    pagination_class = PageNumberPagination
    
    def get_queryset(self):
        # Оптимизированный queryset
        queryset = super().get_queryset()
        queryset = queryset.select_related('profile')
        queryset = queryset.prefetch_related('posts')
        
        # Фильтрация
        if self.request.query_params.get('name'):
            queryset = queryset.filter(
                name__icontains=self.request.query_params.get('name')
            )
        
        return queryset

8. django-q

Для чего: Асинхронные задачи как альтернатива Celery.

# settings.py
INSTALLED_APPS = [
    'django_q',
]

Q_CLUSTER = {
    'name': 'myproject',
    'workers': 4,
    'timeout': 300,
    'retry': 360,
    'queue_limit': 50,
    'orm': 'default',
}
from django_q.tasks import async_task, fetch

# Асинхронное выполнение
task_id = async_task('myapp.tasks.send_email', 
                     to_email='user@example.com',
                     subject='Hello')

# Проверка статуса
result = fetch(task_id)
if result:
    print(f"Результат: {result}")
else:
    print("Задача ещё выполняется")

9. psycopg2 с connection pooling

Для чего: Эффективное подключение к БД.

# settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'mydb',
        'USER': 'postgres',
        'PASSWORD': 'password',
        'HOST': 'localhost',
        'PORT': '5432',
        'CONN_MAX_AGE': 600,  # Connection pooling
        'OPTIONS': {
            'connect_timeout': 10,
        },
    }
}

Или с pgbouncer (внешний pooler):

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'mydb',
        'HOST': 'localhost',
        'PORT': '6432',  # pgbouncer port
    }
}

10. django-queryset-sequence

Для чего: Объединение querysets из разных моделей.

from queryset_sequence import QuerySetSequence

users = User.objects.all()
admins = Admin.objects.all()

# Безопасное объединение
all_people = QuerySetSequence(users, admins)

for person in all_people:
    print(person.name)

11. django-compression

Для чего: Сжатие static файлов.

# settings.py
INSTALLED_APPS = [
    'compressor',
]

COMPRESSED_OFFLINE = True
COMPRESSED_CSS_FILTERS = [
    'compressor.filters.css_default.CssAbsoluteFilter',
    'compressor.filters.cssmin.rCSSMinFilter',
]

12. django-cors-headers (для API)

Для чего: Управление CORS.

INSTALLED_APPS = [
    'corsheaders',
]

MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
]

CORS_ALLOWED_ORIGINS = [
    'https://example.com',
    'https://subdomain.example.com',
]

Практический пример оптимизации

# Плохая реализация
def get_user_posts(user_id):
    user = User.objects.get(id=user_id)  # Запрос 1
    posts = user.posts.all()  # Запрос 2
    for post in posts:  # N запросов
        print(post.author.name)
        for comment in post.comments.all():  # N запросов
            print(comment.text)

# Оптимизированная версия
def get_user_posts(user_id):
    return User.objects.filter(id=user_id).select_related(
        'profile'
    ).prefetch_related(
        Prefetch('posts',
            queryset=Post.objects.select_related('author')
                .prefetch_related('comments'))
    )[0]

# Результат: 1 запрос вместо N+N²

Мой выбор для разных сценариев

  1. Отладка в development → Django Debug Toolbar
  2. Production monitoring → Django Silk (осторожно) или Sentry
  3. Кэширование ORM → django-cachalot
  4. Redis кэш → django-redis
  5. Асинхронные задачи → Celery или django-q
  6. Решение N+1 → select_related/prefetch_related
  7. REST API → DRF с оптимизацией querysets
  8. Connection pooling → CONN_MAX_AGE или pgbouncer
  9. Compression → django-compression

Ключевое правило: сначала профилируй, потом оптимизируй.

Какие используешь библиотеки для оптимизации в Django? | PrepBro