""" Source related views. """ from datetime import datetime from django.contrib.auth.mixins import LoginRequiredMixin from django.core.paginator import Paginator from django.db.models import Count from django.shortcuts import render from django.views import View from ..models import Source from ..utils import parse_pagination_params class SourceListView(LoginRequiredMixin, View): """ View for displaying a list of sources (Source). """ def get(self, request): # Get pagination parameters page_number, items_per_page = parse_pagination_params(request) # Get sorting parameters sort_param = request.GET.get("sort", "-created_at") # Get filter parameters search_query = request.GET.get("search", "").strip() has_coords_average = request.GET.get("has_coords_average") has_coords_kupsat = request.GET.get("has_coords_kupsat") has_coords_valid = request.GET.get("has_coords_valid") has_coords_reference = request.GET.get("has_coords_reference") objitem_count_min = request.GET.get("objitem_count_min", "").strip() objitem_count_max = request.GET.get("objitem_count_max", "").strip() date_from = request.GET.get("date_from", "").strip() date_to = request.GET.get("date_to", "").strip() # Get all Source objects with query optimization sources = Source.objects.select_related( 'created_by__user', 'updated_by__user' ).prefetch_related( 'source_objitems', 'source_objitems__parameter_obj', 'source_objitems__geo_obj' ).annotate( objitem_count=Count('source_objitems') ) # Apply filters # Filter by coords_average presence if has_coords_average == "1": sources = sources.filter(coords_average__isnull=False) elif has_coords_average == "0": sources = sources.filter(coords_average__isnull=True) # Filter by coords_kupsat presence if has_coords_kupsat == "1": sources = sources.filter(coords_kupsat__isnull=False) elif has_coords_kupsat == "0": sources = sources.filter(coords_kupsat__isnull=True) # Filter by coords_valid presence if has_coords_valid == "1": sources = sources.filter(coords_valid__isnull=False) elif has_coords_valid == "0": sources = sources.filter(coords_valid__isnull=True) # Filter by coords_reference presence if has_coords_reference == "1": sources = sources.filter(coords_reference__isnull=False) elif has_coords_reference == "0": sources = sources.filter(coords_reference__isnull=True) # Filter by ObjItem count if objitem_count_min: try: min_count = int(objitem_count_min) sources = sources.filter(objitem_count__gte=min_count) except ValueError: pass if objitem_count_max: try: max_count = int(objitem_count_max) sources = sources.filter(objitem_count__lte=max_count) except ValueError: pass # Filter by creation date range if date_from: try: date_from_obj = datetime.strptime(date_from, "%Y-%m-%d") sources = sources.filter(created_at__gte=date_from_obj) except (ValueError, TypeError): pass if date_to: try: from datetime import timedelta date_to_obj = datetime.strptime(date_to, "%Y-%m-%d") # Add one day to include entire end date date_to_obj = date_to_obj + timedelta(days=1) sources = sources.filter(created_at__lt=date_to_obj) except (ValueError, TypeError): pass # Search by ID if search_query: try: search_id = int(search_query) sources = sources.filter(id=search_id) except ValueError: # If not a number, ignore pass # Apply sorting valid_sort_fields = { "id": "id", "-id": "-id", "created_at": "created_at", "-created_at": "-created_at", "updated_at": "updated_at", "-updated_at": "-updated_at", "objitem_count": "objitem_count", "-objitem_count": "-objitem_count", } if sort_param in valid_sort_fields: sources = sources.order_by(valid_sort_fields[sort_param]) # Create paginator paginator = Paginator(sources, items_per_page) page_obj = paginator.get_page(page_number) # Prepare data for display processed_sources = [] for source in page_obj: # Format coordinates def format_coords(point): if point: longitude = point.coords[0] latitude = point.coords[1] lon = f"{longitude}E" if longitude > 0 else f"{abs(longitude)}W" lat = f"{latitude}N" if latitude > 0 else f"{abs(latitude)}S" return f"{lat} {lon}" return "-" coords_average_str = format_coords(source.coords_average) coords_kupsat_str = format_coords(source.coords_kupsat) coords_valid_str = format_coords(source.coords_valid) coords_reference_str = format_coords(source.coords_reference) # Get count of related ObjItems objitem_count = source.objitem_count processed_sources.append({ 'id': source.id, 'coords_average': coords_average_str, 'coords_kupsat': coords_kupsat_str, 'coords_valid': coords_valid_str, 'coords_reference': coords_reference_str, 'objitem_count': objitem_count, 'created_at': source.created_at, 'updated_at': source.updated_at, 'created_by': source.created_by, 'updated_by': source.updated_by, }) # Prepare context for template context = { 'page_obj': page_obj, 'processed_sources': processed_sources, 'items_per_page': items_per_page, 'available_items_per_page': [50, 100, 500, 1000], 'sort': sort_param, 'search_query': search_query, 'has_coords_average': has_coords_average, 'has_coords_kupsat': has_coords_kupsat, 'has_coords_valid': has_coords_valid, 'has_coords_reference': has_coords_reference, 'objitem_count_min': objitem_count_min, 'objitem_count_max': objitem_count_max, 'date_from': date_from, 'date_to': date_to, 'full_width_page': True, } return render(request, "mainapp/source_list.html", context)