from django.http import HttpResponse, HttpResponseNotFound from .models import * from django.shortcuts import render, redirect from django.contrib import messages from .models import CallbackRequest # Импортируем из models, а не forms from .forms import CallbackForm from django.utils import timezone from datetime import timedelta from .models import PageView, Visitor from django.db.models import Count from django.contrib.auth.decorators import login_required, user_passes_test from django.views.decorators.http import require_GET menu = [ {'title': "Главная", 'url_name': 'home'}, {'title': "Проекты", 'url_name': 'solution'}, # {'title': "Компетенции", 'url_name': 'ability'}, {'title': "Отзывы", 'url_name': 'recall'}, {'title': "Статьи", 'url_name': 'blog'}, {'title': "Обо мне", 'url_name': 'about'} ] # === ДОБАВЬТЕ ЭТИ ФУНКЦИИ ЗДЕСЬ === def get_client_ip(request): """Получаем реальный 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): """Определяем, нужно ли отслеживать запрос""" client_ip = get_client_ip(request) path = request.path # Игнорируемые пути (Nextcloud специфичные) nextcloud_paths = [ '/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 path.startswith('/static/') or path.startswith('/admin/'): return False # Не отслеживаем Nextcloud и Docker запросы if any(path.startswith(p) for p in nextcloud_paths): return False if client_ip in docker_ips: return False return True def track_page_view(request): """Основная функция отслеживания просмотров""" 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], ) except Exception as e: print(f"Error tracking page: {e}") def track_view(view_func): """Декоратор для отслеживания просмотров страниц""" from functools import wraps @wraps(view_func) def _wrapped_view(request, *args, **kwargs): # Отслеживаем просмотр перед выполнением view track_page_view(request) return view_func(request, *args, **kwargs) return _wrapped_view @track_view def index(request): posts = Home.objects.filter(is_published=True) context = { 'posts': posts, 'menu': menu, 'title': "Программист 1С Николай Сердюк - разработка и сопровождение", 'meta_description': "Профессиональный программист 1С с более чем 10-летним опытом. Разработка, доработка, обновление и интеграция систем 1С. Сопровождение 1С.", 'meta_keywords': "программист 1С, разработка 1С, обновление 1С, сопровождение 1С, интеграция 1С, доработка 1С, 1С предприятие 8.3", 'form': CallbackForm() } return render(request, 'programmer/index.html', context=context) @track_view def about(request): context = { 'menu': menu, 'title': "Программист 1С Николай Сердюк - 10+ лет опыта | Услуги 1С", 'meta_description': "Николай Сердюк - сертифицированный программист 1С с 10+ лет опыта. Специализация: обновление 1С, разработка под ключ, интеграция, миграция с 1С 7.7.", 'meta_keywords': "программист 1С Николай Сердюк, обновление 1С, разработка 1С под ключ, интеграция 1С, сертифицированный 1С, миграция 1С 7.7" } return render(request, 'programmer/about.html', context=context) @track_view def solution(request): posts = Solution.objects.filter(is_published=True) context = { 'posts': posts, 'menu': menu, 'meta_description': "Реализованные проекты по автоматизации 1С: складской учет с ТСД, интеграция с оборудованием, миграция с 1С 7.7. Примеры работ и кейсы.", 'meta_keywords': "проекты 1С, автоматизация склада 1С, интеграция ТСД 1С, миграция 1С 7.7, кейсы 1С, примеры работ 1С", 'title': "Проекты автоматизации 1С | Реализованные кейсы и решения", } return render(request, 'programmer/solution.html', context=context) @track_view def ability(request): posts = Competence.objects.filter(is_published=True) context = { 'posts': posts, 'menu': menu, 'title': "Сертификаты и компетенции 1С | Программист 1С Николай Сердюк", 'meta_description': "Сертификаты 1С: Профессионал по платформе 8.3 и БП 3.0. Подтвержденная квалификация программиста 1С с сертификатами фирмы 1С.", 'meta_keywords': "сертификаты 1С, 1С профессионал, компетенции 1С, квалификация программиста 1С, сертифицированный специалист 1С" } return render(request, 'programmer/competence.html', context=context) @track_view def recall(request): posts = Recall.objects.filter(is_published=True) context = { 'posts': posts, 'menu': menu, 'title': "Отзывы клиентов о работе программиста 1С | Реальные кейсы", 'meta_description': "Реальные отзывы клиентов о работе программиста 1С Николая Сердюка. Отзывы от ООО «РОВЕН-Регионы» и других компаний.", 'meta_keywords': "отзывы программист 1С, рекомендации 1С, отзывы клиентов 1С, реальные кейсы 1С, отзыв ООО РОВЕН" } return render(request, 'programmer/recall.html', context=context) def show_post(request, post_id): return HttpResponse(f"Отображение № {post_id}") def pageNotFound(request, exception): return HttpResponseNotFound('

Страница не найдена

') def callback_request(request): if request.method == 'POST': form = CallbackForm(request.POST) if form.is_valid(): # Сохраняем заявку через форму form.save() messages.success(request, '✅ Ваша заявка успешно отправлена! Я свяжусь с вами в ближайшее время.') return redirect('home') else: # Если форма невалидна, показываем ошибки for field, errors in form.errors.items(): for error in errors: messages.error(request, f'❌ Ошибка в поле {form.fields[field].label}: {error}') return redirect('home') # Если GET запрос, просто показываем главную страницу return redirect('home') def is_admin(user): return user.is_staff def is_staff(user): return user.is_staff @login_required @user_passes_test(is_staff) def statistics_view(request): today = timezone.now().date() week_ago = today - timedelta(days=7) # Статистика за сегодня today_views = PageView.objects.filter( timestamp__date=today ).count() # Статистика за неделю weekly_views = PageView.objects.filter( timestamp__date__gte=week_ago ).count() # Всего просмотров total_views = PageView.objects.count() # Популярные страницы за неделю popular_pages = PageView.objects.filter( timestamp__date__gte=week_ago ).values('url').annotate( views=Count('id') ).order_by('-views')[:10] # Уникальные посетители за неделю unique_visitors = Visitor.objects.filter( last_visit__date__gte=week_ago ).count() # Последние посещения recent_views = PageView.objects.select_related().order_by('-timestamp')[:20] today = timezone.now().date() total_callbacks = CallbackRequest.objects.count() today_callbacks = CallbackRequest.objects.filter(time_create__date=today).count() unread_callbacks = CallbackRequest.objects.filter(is_read=False).count() context = { 'today_views': today_views, 'weekly_views': weekly_views, 'total_views': total_views, 'unique_visitors': unique_visitors, 'popular_pages': popular_pages, 'recent_views': recent_views, 'total_callbacks': total_callbacks, 'today_callbacks': today_callbacks, 'unread_callbacks': unread_callbacks, } return render(request, 'admin/statistics.html', context) @require_GET def robots_txt(request): return render(request, 'robots.txt', content_type='text/plain')