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-опроса позволяет добиться плавного пользовательского опыта даже при длительных операциях.