После рефакторинга

This commit is contained in:
2025-11-18 14:44:32 +03:00
parent 55759ec705
commit c8bcd1adf0
56 changed files with 204454 additions and 683 deletions

View File

@@ -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', '')
# Добавить информацию о возможности редактирования для каждой отметки
# и получить имя первого объекта для каждого источника