Фильтр по дате ГЛ. Пока не работает
This commit is contained in:
@@ -227,6 +227,15 @@
|
||||
placeholder="До" value="{{ date_to|default:'' }}">
|
||||
</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 -->
|
||||
<div class="d-grid gap-2 mt-2">
|
||||
<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'));
|
||||
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('/api/source/' + sourceId + '/objitems/')
|
||||
fetch(apiUrl)
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
if (response.status === 404) {
|
||||
|
||||
@@ -176,9 +176,14 @@ class SourceObjItemsAPIView(LoginRequiredMixin, View):
|
||||
"""API endpoint for getting ObjItems related to a Source."""
|
||||
|
||||
def get(self, request, source_id):
|
||||
from datetime import datetime, timedelta
|
||||
from ..models import Source
|
||||
|
||||
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
|
||||
source = Source.objects.prefetch_related(
|
||||
'source_objitems',
|
||||
@@ -198,7 +203,26 @@ class SourceObjItemsAPIView(LoginRequiredMixin, View):
|
||||
).get(id=source_id)
|
||||
|
||||
# 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 = []
|
||||
for objitem in objitems:
|
||||
|
||||
@@ -40,6 +40,8 @@ class SourceListView(LoginRequiredMixin, View):
|
||||
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()
|
||||
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")
|
||||
|
||||
# Get all satellites for filter
|
||||
@@ -50,6 +52,28 @@ class SourceListView(LoginRequiredMixin, View):
|
||||
.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
|
||||
# Using annotate to count ObjItems efficiently (single query with GROUP BY)
|
||||
# Using prefetch_related for reverse ForeignKey relationships to avoid N+1 queries
|
||||
@@ -61,7 +85,7 @@ class SourceListView(LoginRequiredMixin, View):
|
||||
'marks',
|
||||
'marks__created_by__user'
|
||||
).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
|
||||
@@ -130,6 +154,10 @@ class SourceListView(LoginRequiredMixin, View):
|
||||
except (ValueError, TypeError):
|
||||
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
|
||||
if search_query:
|
||||
try:
|
||||
@@ -184,15 +212,33 @@ class SourceListView(LoginRequiredMixin, View):
|
||||
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
|
||||
# Filter objitems by geo date if filter is applied
|
||||
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
|
||||
satellite_names = set()
|
||||
has_lyngsat = False
|
||||
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, 'id_satellite') and objitem.parameter_obj.id_satellite:
|
||||
satellite_names.add(objitem.parameter_obj.id_satellite.name)
|
||||
@@ -247,6 +293,8 @@ class SourceListView(LoginRequiredMixin, View):
|
||||
'objitem_count_max': objitem_count_max,
|
||||
'date_from': date_from,
|
||||
'date_to': date_to,
|
||||
'geo_date_from': geo_date_from,
|
||||
'geo_date_to': geo_date_to,
|
||||
'satellites': 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()))
|
||||
|
||||
Reference in New Issue
Block a user