Compare commits
2 Commits
b5926943d7
...
d54d77dd88
| Author | SHA1 | Date | |
|---|---|---|---|
| d54d77dd88 | |||
|
|
5a9c0bbcc6 |
@ -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')
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
# blog/signals.py
|
||||
from django.db.models.signals import post_save
|
||||
from django.dispatch import receiver
|
||||
from .models import Article
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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
|
||||
@ -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):
|
||||
"""
|
||||
Миксин для добавления меню в контекст.
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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'
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user