diff --git a/OneCprogsite/settings.py b/OneCprogsite/settings.py index 284625b..ca1b958 100644 --- a/OneCprogsite/settings.py +++ b/OneCprogsite/settings.py @@ -45,6 +45,9 @@ X_FRAME_OPTIONS = 'ALLOW-FROM https://metrika.yandex.ru' # ОБЯЗАТЕЛЬНО укажите ваши домены ALLOWED_HOSTS = os.getenv('DJANGO_ALLOWED_HOSTS', 'localhost,127.0.0.1').split(',') +# Исключения для отслеживания +EXCLUDED_IPS = os.getenv('EXCLUDED_IPS', 'localhost,127.0.0.1').split(',') + # Важно для работы за прокси if not DEBUG: SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') diff --git a/blog/signals.py b/blog/signals.py index 227c71f..1e358be 100644 --- a/blog/signals.py +++ b/blog/signals.py @@ -1,4 +1,3 @@ -# blog/signals.py from django.db.models.signals import post_save from django.dispatch import receiver from .models import Article diff --git a/blog/views.py b/blog/views.py index e0de26f..57eec23 100644 --- a/blog/views.py +++ b/blog/views.py @@ -96,7 +96,6 @@ class ArticleDetailView(MenuContextMixin, BreadcrumbMixin, DetailView): def post(self, request, *args, **kwargs): """Обработка формы комментария.""" self.object = self.get_object() - print("POST data:", request.POST) if not request.user.is_authenticated: messages.error(request, "❌ Только авторизованные пользователи могут оставлять комментарии.") @@ -106,7 +105,6 @@ class ArticleDetailView(MenuContextMixin, BreadcrumbMixin, DetailView): if form.is_valid(): parent_id = form.cleaned_data.get('parent_id') - print(f"parent_id from cleaned_data: {parent_id}") parent = None if parent_id: diff --git a/programmer/middleware.py b/programmer/middleware.py index f3d439c..789f971 100644 --- a/programmer/middleware.py +++ b/programmer/middleware.py @@ -1,6 +1,8 @@ -from .models import PageView, Visitor -from django.utils import timezone -from django.db import transaction +from .services import track_page_view +import logging + + +logger = logging.getLogger(__name__) class CSPMiddleware: @@ -20,45 +22,7 @@ class PageViewMiddleware: def __call__(self, request): # Игнорируем статические файлы и админку if not request.path.startswith('/static/') and not request.path.startswith('/admin/'): - self.track_page_view(request) + track_page_view(request) response = self.get_response(request) return response - - def track_page_view(self, request): - try: - with transaction.atomic(): - # Сохраняем просмотр страницы - PageView.objects.create( - url=request.path, - ip_address=self.get_client_ip(request), - user_agent=request.META.get('HTTP_USER_AGENT', ''), - referer=request.META.get('HTTP_REFERER', '') - ) - - # Обновляем статистику посетителя - ip = self.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_client_ip(self, request): - 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 \ No newline at end of file diff --git a/programmer/mixins.py b/programmer/mixins.py index cd256d1..a3031db 100644 --- a/programmer/mixins.py +++ b/programmer/mixins.py @@ -3,17 +3,6 @@ from django.views.generic.base import ContextMixin from .services import track_page_view -class PageViewTrackingMixin(ContextMixin): - """ - Миксин для отслеживания просмотров страниц. - Добавляет трекинг при вызове view. - """ - def dispatch(self, request, *args, **kwargs): - # Отслеживаем просмотр перед обработкой запроса - track_page_view(request) - return super().dispatch(request, *args, **kwargs) - - class MenuContextMixin(ContextMixin): """ Миксин для добавления меню в контекст. diff --git a/programmer/services.py b/programmer/services.py index fcad442..9ae86cb 100644 --- a/programmer/services.py +++ b/programmer/services.py @@ -1,7 +1,7 @@ import logging - from typing import Optional from django.http import HttpRequest +from django.conf import settings from .models import PageView, Visitor from django.utils import timezone @@ -28,14 +28,11 @@ def should_track_request(request: HttpRequest) -> bool: '/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: + + excluded_ips = getattr(settings, 'EXCLUDED_IPS', []) + if client_ip in excluded_ips: return False return True diff --git a/programmer/views.py b/programmer/views.py index c400cf9..5b5eed3 100644 --- a/programmer/views.py +++ b/programmer/views.py @@ -16,7 +16,7 @@ from django.db.models import Count, QuerySet from django.contrib.auth.decorators import login_required, user_passes_test from django.views.decorators.http import require_GET, require_POST from django.views.generic import TemplateView, ListView, CreateView, UpdateView, DetailView -from .mixins import PageViewTrackingMixin, MenuContextMixin, BreadcrumbMixin +from .mixins import MenuContextMixin, BreadcrumbMixin from .services import get_published_queryset, track_page_view from typing import Any, Dict, Type from django.template.loader import render_to_string @@ -26,7 +26,7 @@ from products.models import Order import os -class BasePageView(PageViewTrackingMixin, MenuContextMixin, TemplateView): +class BasePageView(MenuContextMixin, TemplateView): """ Базовый класс для всех страниц сайта. Включает отслеживание просмотров и контекст меню. @@ -34,7 +34,7 @@ class BasePageView(PageViewTrackingMixin, MenuContextMixin, TemplateView): extra_context = {} -class BaseListView(PageViewTrackingMixin, MenuContextMixin, ListView): +class BaseListView(MenuContextMixin, ListView): """ Базовый класс для всех страниц со списками объектов. Включает отслеживание просмотров и контекст меню. @@ -194,14 +194,14 @@ class RecallListView(BaseListView, BreadcrumbMixin): return context -class ProfileView(LoginRequiredMixin, PageViewTrackingMixin, MenuContextMixin, BreadcrumbMixin, TemplateView): +class ProfileView(LoginRequiredMixin, MenuContextMixin, BreadcrumbMixin, TemplateView): template_name = 'programmer/profile.html' def get_breadcrumbs(self): return [{'title': 'Профиль', 'url_name': None}] -class RegisterView(PageViewTrackingMixin, MenuContextMixin, SuccessMessageMixin, BreadcrumbMixin, CreateView): +class RegisterView(MenuContextMixin, SuccessMessageMixin, BreadcrumbMixin, CreateView): """Регистрация нового пользователя""" template_name = 'programmer/register.html' form_class = RegistrationForm @@ -240,7 +240,7 @@ class RegisterView(PageViewTrackingMixin, MenuContextMixin, SuccessMessageMixin, super().__init__(*args, **kwargs) -class ProfileEditView(LoginRequiredMixin, PageViewTrackingMixin, MenuContextMixin, BreadcrumbMixin, UpdateView): +class ProfileEditView(LoginRequiredMixin, MenuContextMixin, BreadcrumbMixin, UpdateView): model = Profile form_class = ProfileForm template_name = 'programmer/profile_edit.html'