Фильтр по дате ГЛ. Пока не работает

This commit is contained in:
2025-11-16 23:58:34 +03:00
parent 8994a0e500
commit c55a41f5fe
3 changed files with 104 additions and 6 deletions

View File

@@ -227,6 +227,15 @@
placeholder="До" value="{{ date_to|default:'' }}"> placeholder="До" value="{{ date_to|default:'' }}">
</div> </div>
<!-- Geo Timestamp Filter -->
<div class="mb-2">
<label class="form-label">Дата ГЛ:</label>
<input type="date" name="geo_date_from" id="geo_date_from" class="form-control form-control-sm mb-1"
placeholder="От" value="{{ geo_date_from|default:'' }}">
<input type="date" name="geo_date_to" id="geo_date_to" class="form-control form-control-sm"
placeholder="До" value="{{ geo_date_to|default:'' }}">
</div>
<!-- Apply Filters and Reset Buttons --> <!-- Apply Filters and Reset Buttons -->
<div class="d-grid gap-2 mt-2"> <div class="d-grid gap-2 mt-2">
<button type="submit" class="btn btn-primary btn-sm">Применить</button> <button type="submit" class="btn btn-primary btn-sm">Применить</button>
@@ -812,8 +821,25 @@ function showSourceDetails(sourceId) {
const modal = new bootstrap.Modal(document.getElementById('sourceDetailsModal')); const modal = new bootstrap.Modal(document.getElementById('sourceDetailsModal'));
modal.show(); modal.show();
// Build URL with filter parameters
const urlParams = new URLSearchParams(window.location.search);
const geoDateFrom = urlParams.get('geo_date_from');
const geoDateTo = urlParams.get('geo_date_to');
let apiUrl = '/api/source/' + sourceId + '/objitems/';
const params = new URLSearchParams();
if (geoDateFrom) {
params.append('geo_date_from', geoDateFrom);
}
if (geoDateTo) {
params.append('geo_date_to', geoDateTo);
}
if (params.toString()) {
apiUrl += '?' + params.toString();
}
// Fetch data from API // Fetch data from API
fetch('/api/source/' + sourceId + '/objitems/') fetch(apiUrl)
.then(response => { .then(response => {
if (!response.ok) { if (!response.ok) {
if (response.status === 404) { if (response.status === 404) {

View File

@@ -176,9 +176,14 @@ class SourceObjItemsAPIView(LoginRequiredMixin, View):
"""API endpoint for getting ObjItems related to a Source.""" """API endpoint for getting ObjItems related to a Source."""
def get(self, request, source_id): def get(self, request, source_id):
from datetime import datetime, timedelta
from ..models import Source from ..models import Source
try: try:
# Get filter parameters from query string
geo_date_from = request.GET.get("geo_date_from", "").strip()
geo_date_to = request.GET.get("geo_date_to", "").strip()
# Load Source with prefetch_related for ObjItem # Load Source with prefetch_related for ObjItem
source = Source.objects.prefetch_related( source = Source.objects.prefetch_related(
'source_objitems', 'source_objitems',
@@ -198,7 +203,26 @@ class SourceObjItemsAPIView(LoginRequiredMixin, View):
).get(id=source_id) ).get(id=source_id)
# Get all related ObjItems, sorted by created_at # Get all related ObjItems, sorted by created_at
objitems = source.source_objitems.all().order_by('created_at') objitems = source.source_objitems.all()
# Apply Geo timestamp filter if provided
if geo_date_from:
try:
geo_date_from_obj = datetime.strptime(geo_date_from, "%Y-%m-%d")
objitems = objitems.filter(geo_obj__timestamp__gte=geo_date_from_obj)
except (ValueError, TypeError):
pass
if geo_date_to:
try:
geo_date_to_obj = datetime.strptime(geo_date_to, "%Y-%m-%d")
# Add one day to include entire end date
geo_date_to_obj = geo_date_to_obj + timedelta(days=1)
objitems = objitems.filter(geo_obj__timestamp__lt=geo_date_to_obj)
except (ValueError, TypeError):
pass
objitems = objitems.order_by('created_at')
objitems_data = [] objitems_data = []
for objitem in objitems: for objitem in objitems:

View File

@@ -40,6 +40,8 @@ class SourceListView(LoginRequiredMixin, View):
objitem_count_max = request.GET.get("objitem_count_max", "").strip() objitem_count_max = request.GET.get("objitem_count_max", "").strip()
date_from = request.GET.get("date_from", "").strip() date_from = request.GET.get("date_from", "").strip()
date_to = request.GET.get("date_to", "").strip() date_to = request.GET.get("date_to", "").strip()
geo_date_from = request.GET.get("geo_date_from", "").strip()
geo_date_to = request.GET.get("geo_date_to", "").strip()
selected_satellites = request.GET.getlist("satellite_id") selected_satellites = request.GET.getlist("satellite_id")
# Get all satellites for filter # Get all satellites for filter
@@ -50,6 +52,28 @@ class SourceListView(LoginRequiredMixin, View):
.order_by("name") .order_by("name")
) )
# Build Q object for geo date filtering
geo_date_q = Q()
has_geo_date_filter = False
if geo_date_from:
try:
geo_date_from_obj = datetime.strptime(geo_date_from, "%Y-%m-%d")
geo_date_q &= Q(source_objitems__geo_obj__timestamp__gte=geo_date_from_obj)
has_geo_date_filter = True
except (ValueError, TypeError):
pass
if geo_date_to:
try:
from datetime import timedelta
geo_date_to_obj = datetime.strptime(geo_date_to, "%Y-%m-%d")
# Add one day to include entire end date
geo_date_to_obj = geo_date_to_obj + timedelta(days=1)
geo_date_q &= Q(source_objitems__geo_obj__timestamp__lt=geo_date_to_obj)
has_geo_date_filter = True
except (ValueError, TypeError):
pass
# Get all Source objects with query optimization # Get all Source objects with query optimization
# Using annotate to count ObjItems efficiently (single query with GROUP BY) # Using annotate to count ObjItems efficiently (single query with GROUP BY)
# Using prefetch_related for reverse ForeignKey relationships to avoid N+1 queries # Using prefetch_related for reverse ForeignKey relationships to avoid N+1 queries
@@ -61,7 +85,7 @@ class SourceListView(LoginRequiredMixin, View):
'marks', 'marks',
'marks__created_by__user' 'marks__created_by__user'
).annotate( ).annotate(
objitem_count=Count('source_objitems') objitem_count=Count('source_objitems', filter=geo_date_q) if has_geo_date_filter else Count('source_objitems')
) )
# Apply filters # Apply filters
@@ -130,6 +154,10 @@ class SourceListView(LoginRequiredMixin, View):
except (ValueError, TypeError): except (ValueError, TypeError):
pass pass
# Filter by Geo timestamp range (only filter sources that have matching objitems)
if has_geo_date_filter:
sources = sources.filter(geo_date_q).distinct()
# Search by ID # Search by ID
if search_query: if search_query:
try: try:
@@ -184,15 +212,33 @@ class SourceListView(LoginRequiredMixin, View):
coords_valid_str = format_coords(source.coords_valid) coords_valid_str = format_coords(source.coords_valid)
coords_reference_str = format_coords(source.coords_reference) coords_reference_str = format_coords(source.coords_reference)
# Get count of related ObjItems # Filter objitems by geo date if filter is applied
objitem_count = source.objitem_count objitems_to_display = source.source_objitems.all()
if geo_date_from or geo_date_to:
if geo_date_from:
try:
geo_date_from_obj = datetime.strptime(geo_date_from, "%Y-%m-%d")
objitems_to_display = objitems_to_display.filter(geo_obj__timestamp__gte=geo_date_from_obj)
except (ValueError, TypeError):
pass
if geo_date_to:
try:
from datetime import timedelta
geo_date_to_obj = datetime.strptime(geo_date_to, "%Y-%m-%d")
geo_date_to_obj = geo_date_to_obj + timedelta(days=1)
objitems_to_display = objitems_to_display.filter(geo_obj__timestamp__lt=geo_date_to_obj)
except (ValueError, TypeError):
pass
# Get count of related ObjItems (filtered)
objitem_count = objitems_to_display.count()
# Get satellites for this source and check for LyngSat # Get satellites for this source and check for LyngSat
satellite_names = set() satellite_names = set()
has_lyngsat = False has_lyngsat = False
lyngsat_id = None lyngsat_id = None
for objitem in source.source_objitems.all(): for objitem in objitems_to_display:
if hasattr(objitem, 'parameter_obj') and objitem.parameter_obj: if hasattr(objitem, 'parameter_obj') and objitem.parameter_obj:
if hasattr(objitem.parameter_obj, 'id_satellite') and objitem.parameter_obj.id_satellite: if hasattr(objitem.parameter_obj, 'id_satellite') and objitem.parameter_obj.id_satellite:
satellite_names.add(objitem.parameter_obj.id_satellite.name) satellite_names.add(objitem.parameter_obj.id_satellite.name)
@@ -247,6 +293,8 @@ class SourceListView(LoginRequiredMixin, View):
'objitem_count_max': objitem_count_max, 'objitem_count_max': objitem_count_max,
'date_from': date_from, 'date_from': date_from,
'date_to': date_to, 'date_to': date_to,
'geo_date_from': geo_date_from,
'geo_date_to': geo_date_to,
'satellites': satellites, 'satellites': satellites,
'selected_satellites': [ 'selected_satellites': [
int(x) if isinstance(x, str) else x for x in selected_satellites if (isinstance(x, int) or (isinstance(x, str) and x.isdigit())) int(x) if isinstance(x, str) else x for x in selected_satellites if (isinstance(x, int) or (isinstance(x, str) and x.isdigit()))