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

Почему не стоит запускать приложение через manage.py в Django?

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

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

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

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

Почему не стоит использовать manage.py для production Django приложений

Это очень важный вопрос о различии между development и production окружением. manage.py runserver предназначен ТОЛЬКО для локальной разработки, а не для реальных приложений.

1. manage.py runserver — это development сервер

Что такое manage.py runserver?

# Development сервер Django
$ python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced).
Starting development server at http://127.0.0.1:8000/

# Сервер автоматически перезагружается при изменении кода
# Это удобно для разработки, но опасно для production

Это сервер, встроенный в Django, предназначенный только для локальной разработки на одной машине.

2. Проблемы development сервера для production

Проблема 1: Однопоточная обработка

# manage.py runserver обрабатывает запросы последовательно
# Если приложение медленное, все остальные запросы ждут

from django.http import HttpResponse
import time

def slow_view(request):
    time.sleep(5)  # Медленная операция
    return HttpResponse("Готово")

def fast_view(request):
    return HttpResponse("Быстро")

# Если запрос пришёл в slow_view, fast_view будет ждать 5 секунд!
# В production это критическая проблема

Проблема 2: Нет обработки ошибок

# Если произойдёт ошибка в коде, development сервер может упасть
$ python manage.py runserver
# После ошибки
Traceback (most recent call last):
  File "manage.py", line 8, in <module>
    ...
Exception: Something went wrong

# Приложение просто падает. Нет автоматического перезапуска.

Проблема 3: Нет производительности

# Development сервер не оптимизирован для скорости
# Время ответа значительно больше, чем на production сервере

# Development (manage.py runserver): ~500ms
# Production (gunicorn + nginx): ~50ms

# В production может быть 1000+ одновременных пользователей
# Development сервер может обработать максимум 1-2

Проблема 4: Нет сессионности

# Development сервер не может масштабироваться на несколько машин
# В production часто нужно распределение нагрузки

# Это невозможно с manage.py runserver
# Нужно использовать production сервер (gunicorn, uWSGI)

Проблема 5: Автоматическая перезагрузка при изменениях

# Development сервер пересчитывает весь проект при изменении файлов
# В production это может привести к потере текущих запросов

$ python manage.py runserver
Watching for file changes with StatReloader
# Когда вы сохраняете файл...
django.core.exceptions.ImproperlyConfigured:
    # Сервер перезагружается, все текущие соединения разрываются

3. Правильное решение: Production сервер

Архитектура production приложения

Клиент
   |
   v
Nginx (обратный прокси, static файлы)
   |
   v
Gunicorn (WSGI сервер, несколько workers)
   |
   +-> Django процесс 1
   +-> Django процесс 2
   +-> Django процесс 3
   +-> Django процесс 4
   |
   v
PostgreSQL (база данных)
Redis (кэш, сессии)

Gunicorn — правильный сервер приложений

# Установка
$ pip install gunicorn

# Запуск с 4 workers
$ gunicorn myproject.wsgi:application --workers 4 --bind 0.0.0.0:8000

# Вывод
[2024-03-23 10:30:45 +0000] [1234] [INFO] Starting gunicorn 21.0.0
[2024-03-23 10:30:45 +0000] [1234] [INFO] Listening at: http://0.0.0.0:8000
[2024-03-23 10:30:45 +0000] [1234] [INFO] Workers: 4

# Теперь может обработать много одновременных запросов

Конфигурация Gunicorn

# gunicorn.conf.py
import multiprocessing

# Число workers = 2 * CPU cores + 1
workers = multiprocessing.cpu_count() * 2 + 1
worker_class = 'sync'  # или 'gevent' для асинхронности
worker_connections = 1000
max_requests = 1000
max_requests_jitter = 50
timeout = 30
keepalive = 2
bind = '0.0.0.0:8000'
accesslog = '/var/log/gunicorn/access.log'
errorlog = '/var/log/gunicorn/error.log'
loglevel = 'info'

4. Сравнение: Development vs Production

# development/settings.py (для разработки)
DEBUG = True  # Показываем ошибки
ALLOWED_HOSTS = ['localhost', '127.0.0.1']
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': 'db.sqlite3',
    }
}

# production/settings.py (для боевого сервера)
DEBUG = False  # Скрываем ошибки
ALLOWED_HOSTS = ['example.com', 'www.example.com']
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'myapp_db',
        'USER': 'myapp',
        'PASSWORD': 'secure_password',
        'HOST': 'db.example.com',
        'PORT': '5432',
    }
}

STATIC_ROOT = '/var/www/static/'
STATIC_URL = 'https://cdn.example.com/static/'

5. Полный stack для production

Docker Compose пример

version: '3.8'

services:
  web:
    image: myapp:latest
    command: gunicorn myproject.wsgi:application --workers 4 --bind 0.0.0.0:8000
    ports:
      - "8000:8000"
    environment:
      - DEBUG=False
      - DJANGO_SETTINGS_MODULE=myproject.settings.production
    depends_on:
      - db
      - redis
    volumes:
      - ./static:/app/static
      - ./media:/app/media
  
  db:
    image: postgres:15
    environment:
      - POSTGRES_DB=myapp_db
      - POSTGRES_USER=myapp
      - POSTGRES_PASSWORD=secure_password
    volumes:
      - ./data/postgres:/var/lib/postgresql/data
  
  redis:
    image: redis:7
    ports:
      - "6379:6379"
  
  nginx:
    image: nginx:latest
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./static:/static:ro
      - ./media:/media:ro
    depends_on:
      - web

Nginx конфигурация

upstream django {
    server web:8000;  # Обращаемся к gunicorn
}

server {
    listen 80;
    server_name example.com www.example.com;
    client_max_body_size 20M;

    location /static/ {
        alias /static/;
    }

    location /media/ {
        alias /media/;
    }

    location / {
        proxy_pass http://django;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_redirect off;
    }
}

6. Сравнение производительности

# benchmark.py
import requests
import time
from concurrent.futures import ThreadPoolExecutor

def make_request():
    return requests.get('http://localhost/api/data')

# Development (manage.py runserver)
# Результат: 5 запросов/сек, время ответа ~200ms

# Production (gunicorn + nginx)
# Результат: 500 запросов/сек, время ответа ~20ms

# Production в 100 раз быстрее!

7. Когда можно использовать manage.py?

# ✅ Правильное использование manage.py

# Локальная разработка
$ python manage.py runserver

# Миграции базы данных
$ python manage.py migrate

# Создание суперпользователя
$ python manage.py createsuperuser

# Загрузка данных
$ python manage.py loaddata fixtures.json

# Кастомные команды
$ python manage.py mycustom_command

# ❌ НИКОГДА в production
$ python manage.py runserver  # Production запуск — ОПАСНО!

8. Правильный процесс запуска

# Локальная разработка
$ python manage.py migrate
$ python manage.py runserver

# Production
$ python manage.py migrate  # Выполнить миграции
$ gunicorn myproject.wsgi:application --workers 4  # Запустить приложение
$ # Nginx уже проксирует трафик на gunicorn

Резюме

manage.py runserver:

  • ✅ Хорош для локальной разработки
  • ❌ Однопоточный
  • ❌ Медленный
  • ❌ Не масштабируется
  • ❌ Нет балансировки нагрузки
  • ❌ Нет обработки ошибок

Gunicorn (Production):

  • ✅ Многопроцессный
  • ✅ Быстрый
  • ✅ Масштабируется
  • ✅ Можно использовать несколько workers
  • ✅ Правильная обработка ошибок
  • ✅ Совместим с Nginx

Ключевые выводы

  1. manage.py runserver предназначен ТОЛЬКО для разработки — никогда не используй в production
  2. В production используй gunicorn или другой WSGI сервер — они специально разработаны для этого
  3. Используй несколько workers — для обработки множества одновременных запросов
  4. Поставь Nginx впереди — для проксирования трафика и раздачи статических файлов
  5. Настрой отдельные settings — development и production должны иметь разные конфигурации

Эта архитектура позволяет обслуживать тысячи пользователей одновременно и обеспечивает надёжность и производительность production приложения.