После рефакторинга
This commit is contained in:
@@ -18,10 +18,17 @@ class ObjectMarksListView(LoginRequiredMixin, ListView):
|
||||
model = Source
|
||||
template_name = "mainapp/object_marks.html"
|
||||
context_object_name = "sources"
|
||||
paginate_by = 50
|
||||
|
||||
def get_paginate_by(self, queryset):
|
||||
"""Получить количество элементов на странице из параметров запроса"""
|
||||
from mainapp.utils import parse_pagination_params
|
||||
_, items_per_page = parse_pagination_params(self.request, default_per_page=50)
|
||||
return items_per_page
|
||||
|
||||
def get_queryset(self):
|
||||
"""Получить queryset с предзагруженными связанными данными"""
|
||||
from django.db.models import Count, Max
|
||||
|
||||
queryset = Source.objects.prefetch_related(
|
||||
'source_objitems',
|
||||
'source_objitems__parameter_obj',
|
||||
@@ -30,17 +37,69 @@ class ObjectMarksListView(LoginRequiredMixin, ListView):
|
||||
'marks',
|
||||
queryset=ObjectMark.objects.select_related('created_by__user').order_by('-timestamp')
|
||||
)
|
||||
).order_by('-updated_at')
|
||||
).annotate(
|
||||
mark_count=Count('marks'),
|
||||
last_mark_date=Max('marks__timestamp')
|
||||
)
|
||||
|
||||
# Фильтрация по спутнику
|
||||
satellite_id = self.request.GET.get('satellite')
|
||||
if satellite_id:
|
||||
queryset = queryset.filter(source_objitems__parameter_obj__id_satellite_id=satellite_id).distinct()
|
||||
# Фильтрация по спутникам (мультивыбор)
|
||||
satellite_ids = self.request.GET.getlist('satellite_id')
|
||||
if satellite_ids:
|
||||
queryset = queryset.filter(source_objitems__parameter_obj__id_satellite_id__in=satellite_ids).distinct()
|
||||
|
||||
# Поиск по имени объекта
|
||||
# Фильтрация по статусу (есть/нет отметок)
|
||||
mark_status = self.request.GET.get('mark_status')
|
||||
if mark_status == 'with_marks':
|
||||
queryset = queryset.filter(mark_count__gt=0)
|
||||
elif mark_status == 'without_marks':
|
||||
queryset = queryset.filter(mark_count=0)
|
||||
|
||||
# Фильтрация по дате отметки
|
||||
date_from = self.request.GET.get('date_from')
|
||||
date_to = self.request.GET.get('date_to')
|
||||
if date_from:
|
||||
from django.utils.dateparse import parse_date
|
||||
parsed_date = parse_date(date_from)
|
||||
if parsed_date:
|
||||
queryset = queryset.filter(marks__timestamp__date__gte=parsed_date).distinct()
|
||||
if date_to:
|
||||
from django.utils.dateparse import parse_date
|
||||
parsed_date = parse_date(date_to)
|
||||
if parsed_date:
|
||||
queryset = queryset.filter(marks__timestamp__date__lte=parsed_date).distinct()
|
||||
|
||||
# Фильтрация по пользователям (мультивыбор)
|
||||
user_ids = self.request.GET.getlist('user_id')
|
||||
if user_ids:
|
||||
queryset = queryset.filter(marks__created_by_id__in=user_ids).distinct()
|
||||
|
||||
# Поиск по имени объекта или ID
|
||||
search_query = self.request.GET.get('search', '').strip()
|
||||
if search_query:
|
||||
queryset = queryset.filter(source_objitems__name__icontains=search_query).distinct()
|
||||
from django.db.models import Q
|
||||
try:
|
||||
# Попытка поиска по ID
|
||||
source_id = int(search_query)
|
||||
queryset = queryset.filter(Q(id=source_id) | Q(source_objitems__name__icontains=search_query)).distinct()
|
||||
except ValueError:
|
||||
# Поиск только по имени
|
||||
queryset = queryset.filter(source_objitems__name__icontains=search_query).distinct()
|
||||
|
||||
# Сортировка
|
||||
sort = self.request.GET.get('sort', '-id')
|
||||
allowed_sorts = ['id', '-id', 'created_at', '-created_at', 'last_mark_date', '-last_mark_date', 'mark_count', '-mark_count']
|
||||
if sort in allowed_sorts:
|
||||
# Для сортировки по last_mark_date нужно обработать NULL значения
|
||||
if 'last_mark_date' in sort:
|
||||
from django.db.models import F
|
||||
from django.db.models.functions import Coalesce
|
||||
queryset = queryset.order_by(
|
||||
Coalesce(F('last_mark_date'), F('created_at')).desc() if sort.startswith('-') else Coalesce(F('last_mark_date'), F('created_at')).asc()
|
||||
)
|
||||
else:
|
||||
queryset = queryset.order_by(sort)
|
||||
else:
|
||||
queryset = queryset.order_by('-id')
|
||||
|
||||
return queryset
|
||||
|
||||
@@ -48,7 +107,32 @@ class ObjectMarksListView(LoginRequiredMixin, ListView):
|
||||
"""Добавить дополнительные данные в контекст"""
|
||||
context = super().get_context_data(**kwargs)
|
||||
from mainapp.models import Satellite
|
||||
context['satellites'] = Satellite.objects.all().order_by('name')
|
||||
from mainapp.utils import parse_pagination_params
|
||||
|
||||
# Данные для фильтров - только спутники, у которых есть источники
|
||||
context['satellites'] = Satellite.objects.filter(
|
||||
parameters__objitem__source__isnull=False
|
||||
).distinct().order_by('name')
|
||||
|
||||
context['users'] = CustomUser.objects.select_related('user').filter(
|
||||
marks_created__isnull=False
|
||||
).distinct().order_by('user__username')
|
||||
|
||||
# Параметры пагинации
|
||||
page_number, items_per_page = parse_pagination_params(self.request, default_per_page=50)
|
||||
context['items_per_page'] = items_per_page
|
||||
context['available_items_per_page'] = [25, 50, 100, 200]
|
||||
|
||||
# Параметры поиска и сортировки
|
||||
context['search_query'] = self.request.GET.get('search', '')
|
||||
context['sort'] = self.request.GET.get('sort', '-id')
|
||||
|
||||
# Параметры фильтров для отображения в UI (мультивыбор)
|
||||
context['selected_satellites'] = [int(x) for x in self.request.GET.getlist('satellite_id') if x.isdigit()]
|
||||
context['selected_users'] = [int(x) for x in self.request.GET.getlist('user_id') if x.isdigit()]
|
||||
context['filter_mark_status'] = self.request.GET.get('mark_status', '')
|
||||
context['filter_date_from'] = self.request.GET.get('date_from', '')
|
||||
context['filter_date_to'] = self.request.GET.get('date_to', '')
|
||||
|
||||
# Добавить информацию о возможности редактирования для каждой отметки
|
||||
# и получить имя первого объекта для каждого источника
|
||||
|
||||
Reference in New Issue
Block a user