Django парсинг: как отобразить загрузку с авто-завершением

    При разработке веб-приложений на Django часто возникает задача парсинга внешних данных по заданным параметрам. Пользователь ожидает увидеть результат через несколько секунд, но во время обработки необходимо показывать индикатор загрузки. В этой статье разберём, как организовать асинхронный парсинг с отображением прогресса и автоматическим выводом полученной информации.

    Архитектура решения для Django

    Для корректной работы нам потребуется три компонента:

    • Фоновый воркер - Celery или django-q для выполнения парсинга без блокировки основного потока.
    • API-эндпоинт - возвращает статус задачи (в процессе / завершена).
    • Фронтенд - JavaScript (fetch/Ajax) периодически проверяет статус и обновляет интерфейс.

    Шаг 1: Настройка Celery для асинхронного парсинга

    Установите Celery и Redis (или RabbitMQ) в качестве брокера. Создайте задачу, которая выполняет парсинг и сохраняет результат в кеш или базу данных:

    from celery import shared_task
    from django.core.cache import cache
    
    @shared_task(bind=True)
    def parse_data_task(self, params):
        # Имитация длительного парсинга (5 секунд)
        import time
        time.sleep(5)
        result = {'status': 'done', 'data': 'Ваша распарсенная информация'}
        cache.set(f'parse_result_{self.request.id}', result, timeout=300)
        return result

    Шаг 2: Создание вьюшки для запуска и проверки статуса

    Во view запускаем задачу и возвращаем её ID. Отдельный эндпоинт возвращает статус по ID:

    from django.http import JsonResponse
    from .tasks import parse_data_task
    
    def start_parse(request):
        task = parse_data_task.delay(request.GET.get('params'))
        return JsonResponse({'task_id': task.id})
    
    def get_parse_status(request, task_id):
        result = cache.get(f'parse_result_{task_id}')
        if result:
            return JsonResponse({'status': 'completed', 'data': result})
        else:
            return JsonResponse({'status': 'processing'})

    Шаг 3: Фронтенд с индикатором загрузки и авто-завершением

    Напишем простой JavaScript, который запускает парсинг, показывает спиннер и через 5 секунд автоматически отображает результат:

    <div id=\"loader\" style=\"display:none;\">Загрузка...</div>
    <div id=\"result\"></div>
    <button onclick=\"startParsing()\">Начать парсинг</button>
    
    <script>
    function startParsing() {
        document.getElementById('loader').style.display = 'block';
        fetch('/start-parse/?params=example')
            .then(r => r.json())
            .then(data => {
                const taskId = data.task_id;
                // Проверяем статус каждые 500 мс
                const interval = setInterval(() => {
                    fetch(`/status/${taskId}/`)
                        .then(r => r.json())
                        .then(status => {
                            if (status.status === 'completed') {
                                clearInterval(interval);
                                document.getElementById('loader').style.display = 'none';
                                document.getElementById('result').innerText = status.data.data;
                            }
                        });
                }, 500);
            });
    }
    </script>

    Альтернативные подходы без Celery

    Если ваш проект небольшой, можно обойтись без Celery, используя django-channels или обычный polling с сохранением статуса в сессии. Однако для продакшена рекомендуется именно Celery - он гарантирует выполнение задачи даже при перезагрузке сервера.

    Важные нюансы при реализации

    • Всегда устанавливайте timeout для задачи, чтобы избежать зависаний.
    • Кешируйте результаты парсинга - это ускорит повторный запрос тех же данных.
    • Для защиты от CSRF используйте декоратор @csrf_exempt на вьюшках, вызываемых через JavaScript (или передавайте токен).

    Заключение

    Теперь вы знаете, как реализовать парсинг в Django с отображением индикатора загрузки и автоматическим выводом результата. Комбинация Celery, кеширования и простого JavaScript-опроса позволяет добиться плавного пользовательского опыта даже при длительных операциях.

    Часто задаваемые вопросы