добавил удаление таймлапсов
All checks were successful
Deploy timelaps / deploy (push) Successful in 5s
All checks were successful
Deploy timelaps / deploy (push) Successful in 5s
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import logging
|
||||
import subprocess
|
||||
import sys
|
||||
from datetime import date
|
||||
|
||||
from django.conf import settings
|
||||
from django.http import FileResponse, Http404
|
||||
@@ -9,6 +10,7 @@ from django.urls import reverse
|
||||
from django.views.decorators.http import require_POST
|
||||
|
||||
from .models import Camera, TimelapseJob
|
||||
from .services.jobs import delete_job_and_artifacts
|
||||
from .services.cameras import (
|
||||
create_cameras_from_candidates,
|
||||
discover_camera_candidates,
|
||||
@@ -58,14 +60,39 @@ def camera_preview(request, camera_id: int):
|
||||
return FileResponse(path.open('rb'), content_type='image/jpeg')
|
||||
|
||||
|
||||
def _parse_iso_date(value: str | None) -> date | None:
|
||||
"""Парсит дату YYYY-MM-DD из query string."""
|
||||
if not value:
|
||||
return None
|
||||
try:
|
||||
return date.fromisoformat(value)
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
|
||||
def job_list(request):
|
||||
"""Отображает таблицу задач и признак активности очереди для автообновления."""
|
||||
qs = TimelapseJob.objects.select_related('camera').all()
|
||||
|
||||
camera_id = request.GET.get('camera')
|
||||
if camera_id:
|
||||
qs = qs.filter(camera_id=camera_id)
|
||||
|
||||
status = request.GET.get('status')
|
||||
if status in {c[0] for c in TimelapseJob.Status.choices}:
|
||||
qs = qs.filter(status=status)
|
||||
|
||||
created_from = _parse_iso_date(request.GET.get('created_from'))
|
||||
if created_from:
|
||||
qs = qs.filter(created_at__date__gte=created_from)
|
||||
|
||||
created_to = _parse_iso_date(request.GET.get('created_to'))
|
||||
if created_to:
|
||||
qs = qs.filter(created_at__date__lte=created_to)
|
||||
|
||||
jobs = qs.order_by('-created_at')[:200]
|
||||
has_active_jobs = qs.filter(status__in=[TimelapseJob.Status.PLANNED, TimelapseJob.Status.RUNNING]).exists()
|
||||
|
||||
return render(
|
||||
request,
|
||||
'camlaps/job_list.html',
|
||||
@@ -74,6 +101,15 @@ def job_list(request):
|
||||
'queue_started': request.GET.get('started'),
|
||||
'retried': request.GET.get('retried'),
|
||||
'has_active_jobs': has_active_jobs,
|
||||
'cameras': Camera.objects.order_by('name'),
|
||||
'status_choices': TimelapseJob.Status.choices,
|
||||
'filters': {
|
||||
'camera': camera_id or '',
|
||||
'status': status or '',
|
||||
'created_from': request.GET.get('created_from', ''),
|
||||
'created_to': request.GET.get('created_to', ''),
|
||||
},
|
||||
'deleted': request.GET.get('deleted'),
|
||||
},
|
||||
)
|
||||
|
||||
@@ -175,6 +211,21 @@ def retry_job(request, job_id: int):
|
||||
return redirect(f"{reverse('camlaps:job_list')}?retried={job_id}")
|
||||
|
||||
|
||||
@require_POST
|
||||
def delete_job(request, job_id: int):
|
||||
"""Удаляет задачу и её артефакты (mp4) при наличии."""
|
||||
logger.info('job:delete:start job_id=%s', job_id)
|
||||
job = get_object_or_404(TimelapseJob, pk=job_id)
|
||||
|
||||
if job.status == TimelapseJob.Status.RUNNING:
|
||||
logger.info('job:delete:done job_id=%s blocked=running', job_id)
|
||||
return redirect(f"{reverse('camlaps:job_list')}?deleted=running")
|
||||
|
||||
delete_job_and_artifacts(job_id)
|
||||
logger.info('job:delete:done job_id=%s', job_id)
|
||||
return redirect(f"{reverse('camlaps:job_list')}?deleted={job_id}")
|
||||
|
||||
|
||||
def job_detail(request, job_id: int):
|
||||
job = get_object_or_404(TimelapseJob.objects.select_related('camera'), pk=job_id)
|
||||
video_url = None
|
||||
|
||||
Reference in New Issue
Block a user