from typing import Optional from django.http import HttpRequest from .models import PageView, Visitor from django.utils import timezone from typing import Type from django.db.models import Model, QuerySet def get_client_ip(request: HttpRequest) -> str: """Получаем реальный IP клиента.""" x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR') if x_forwarded_for: ip = x_forwarded_for.split(',')[0] else: ip = request.META.get('REMOTE_ADDR', '') return ip def should_track_request(request: HttpRequest) -> bool: """Определяем, нужно ли отслеживать запрос.""" client_ip = get_client_ip(request) path = request.path # Игнорируемые пути ignored_paths = [ '/static/', '/admin/', '/index.php', '/status.php', '/cron', '/remote.php', '/ocs', '/apps/', '/custom_apps/', ] # Игнорируемые IP (Docker сети) docker_ips = [ '192.168.64.1', '192.168.65.1', '172.17.0.1', '172.18.0.1', '172.19.0.1', ] if any(path.startswith(p) for p in ignored_paths): return False if client_ip in docker_ips: return False return True def track_page_view(request: HttpRequest) -> None: """Основная функция отслеживания просмотров.""" if not should_track_request(request): return try: # Сохраняем просмотр страницы PageView.objects.create( url=request.path, ip_address=get_client_ip(request), user_agent=request.META.get('HTTP_USER_AGENT', '')[:500], referer=request.META.get('HTTP_REFERER', '')[:500], ) # Обновляем статистику посетителя ip = get_client_ip(request) visitor, created = Visitor.objects.get_or_create( ip_address=ip, defaults={ 'first_visit': timezone.now(), 'last_visit': timezone.now() } ) if not created: visitor.last_visit = timezone.now() visitor.visit_count += 1 visitor.save() except Exception as e: # В продакшене лучше использовать логирование print(f"Error tracking page view: {e}") def get_published_queryset(model_class, order_by: str = '-time_create'): """ Возвращает QuerySet опубликованных записей для модели. Args: model_class: Класс модели Django order_by: Поле для сортировки Returns: QuerySet или пустой список, если поле is_published отсутствует """ if hasattr(model_class, 'is_published'): return model_class.objects.filter(is_published=True).order_by(order_by) return model_class.objects.none()