81 lines
2.4 KiB
Python
81 lines
2.4 KiB
Python
import logging
|
|
|
|
from typing import Optional
|
|
from django.http import HttpRequest
|
|
from .models import PageView, Visitor
|
|
from django.utils import timezone
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
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/',
|
|
]
|
|
|
|
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:
|
|
logger.exception('Ошибка при трекинге просмотра страницы: %s', request.path)
|
|
|
|
|
|
def get_published_queryset(model_class, order_by: str = '-time_create'):
|
|
"""
|
|
Возвращает QuerySet опубликованных записей для модели.
|
|
"""
|
|
if hasattr(model_class, 'is_published'):
|
|
return model_class.objects.filter(is_published=True).order_by(order_by)
|
|
return model_class.objects.none() |