from django.http import FileResponse, Http404 from django.shortcuts import get_object_or_404, redirect, render from django.urls import reverse from .models import Camera, TimelapseJob from .services.cameras import get_camera_lastsnap_path, is_storage_available, list_active_cameras def index(request): cameras = list_active_cameras() context = { 'cameras': cameras, 'storage_available': is_storage_available(), } return render(request, 'camlaps/index.html', context) def camera_preview(request, camera_id: int): camera = get_object_or_404(Camera, pk=camera_id, is_active=True) path = get_camera_lastsnap_path(camera) if not path: raise Http404 return FileResponse(path.open('rb'), content_type='image/jpeg') 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) jobs = qs.order_by('-created_at')[:200] return render(request, 'camlaps/job_list.html', {'jobs': jobs}) def job_detail(request, job_id: int): job = get_object_or_404(TimelapseJob.objects.select_related('camera'), pk=job_id) video_url = None if job.output_rel_path: rel = job.output_rel_path.lstrip('/') if rel.startswith('timelapses/'): video_url = '/' + rel else: video_url = '/timelapses/' + rel.split('/')[-1] return render(request, 'camlaps/job_detail.html', {'job': job, 'video_url': video_url}) def job_create(request, camera_id: int): from .forms import TimelapseJobCreateForm camera = get_object_or_404(Camera, pk=camera_id, is_active=True) if request.method == 'POST': form = TimelapseJobCreateForm(request.POST) if form.is_valid(): job = form.save(commit=False) job.camera = camera job.save() return redirect(reverse('camlaps:job_detail', kwargs={'job_id': job.id})) else: form = TimelapseJobCreateForm() sampling_choices = TimelapseJob.SamplingPreset.choices sampling_max = len(TimelapseJob.SAMPLING_PRESET_MINUTES) - 1 return render( request, 'camlaps/job_create.html', { 'camera': camera, 'form': form, 'sampling_choices': sampling_choices, 'sampling_max': sampling_max, }, )