diff --git a/.gitignore b/.gitignore
index 161feaf..1e69eed 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,4 +21,9 @@ ENV/
# OS
.DS_Store
-Thumbs.db
\ No newline at end of file
+Thumbs.db
+
+# Project specific
+*.log
+*.pot
+*.py[co]
\ No newline at end of file
diff --git a/OneCprogsite/OneCprogsite/__pycache__/settings.cpython-310.pyc b/OneCprogsite/OneCprogsite/__pycache__/settings.cpython-310.pyc
deleted file mode 100644
index e572069..0000000
Binary files a/OneCprogsite/OneCprogsite/__pycache__/settings.cpython-310.pyc and /dev/null differ
diff --git a/OneCprogsite/OneCprogsite/__pycache__/urls.cpython-310.pyc b/OneCprogsite/OneCprogsite/__pycache__/urls.cpython-310.pyc
deleted file mode 100644
index 382208c..0000000
Binary files a/OneCprogsite/OneCprogsite/__pycache__/urls.cpython-310.pyc and /dev/null differ
diff --git a/OneCprogsite/OneCprogsite/__pycache__/wsgi.cpython-310.pyc b/OneCprogsite/OneCprogsite/__pycache__/wsgi.cpython-310.pyc
deleted file mode 100644
index ebfdfae..0000000
Binary files a/OneCprogsite/OneCprogsite/__pycache__/wsgi.cpython-310.pyc and /dev/null differ
diff --git a/OneCprogsite/programmer/__pycache__/admin.cpython-310.pyc b/OneCprogsite/programmer/__pycache__/admin.cpython-310.pyc
deleted file mode 100644
index 38271a2..0000000
Binary files a/OneCprogsite/programmer/__pycache__/admin.cpython-310.pyc and /dev/null differ
diff --git a/OneCprogsite/programmer/__pycache__/apps.cpython-310.pyc b/OneCprogsite/programmer/__pycache__/apps.cpython-310.pyc
deleted file mode 100644
index 1bc3cb6..0000000
Binary files a/OneCprogsite/programmer/__pycache__/apps.cpython-310.pyc and /dev/null differ
diff --git a/OneCprogsite/programmer/__pycache__/context_processors.cpython-310.pyc b/OneCprogsite/programmer/__pycache__/context_processors.cpython-310.pyc
deleted file mode 100644
index bb6b4c0..0000000
Binary files a/OneCprogsite/programmer/__pycache__/context_processors.cpython-310.pyc and /dev/null differ
diff --git a/OneCprogsite/programmer/__pycache__/forms.cpython-310.pyc b/OneCprogsite/programmer/__pycache__/forms.cpython-310.pyc
deleted file mode 100644
index 8fdc086..0000000
Binary files a/OneCprogsite/programmer/__pycache__/forms.cpython-310.pyc and /dev/null differ
diff --git a/OneCprogsite/programmer/__pycache__/middleware.cpython-310.pyc b/OneCprogsite/programmer/__pycache__/middleware.cpython-310.pyc
deleted file mode 100644
index 9fc794e..0000000
Binary files a/OneCprogsite/programmer/__pycache__/middleware.cpython-310.pyc and /dev/null differ
diff --git a/OneCprogsite/programmer/__pycache__/models.cpython-310.pyc b/OneCprogsite/programmer/__pycache__/models.cpython-310.pyc
deleted file mode 100644
index 90f1ff9..0000000
Binary files a/OneCprogsite/programmer/__pycache__/models.cpython-310.pyc and /dev/null differ
diff --git a/OneCprogsite/programmer/__pycache__/sitemaps.cpython-310.pyc b/OneCprogsite/programmer/__pycache__/sitemaps.cpython-310.pyc
deleted file mode 100644
index 46831ac..0000000
Binary files a/OneCprogsite/programmer/__pycache__/sitemaps.cpython-310.pyc and /dev/null differ
diff --git a/OneCprogsite/programmer/__pycache__/urls.cpython-310.pyc b/OneCprogsite/programmer/__pycache__/urls.cpython-310.pyc
deleted file mode 100644
index b007e84..0000000
Binary files a/OneCprogsite/programmer/__pycache__/urls.cpython-310.pyc and /dev/null differ
diff --git a/OneCprogsite/programmer/__pycache__/views.cpython-310.pyc b/OneCprogsite/programmer/__pycache__/views.cpython-310.pyc
deleted file mode 100644
index 3c4cca7..0000000
Binary files a/OneCprogsite/programmer/__pycache__/views.cpython-310.pyc and /dev/null differ
diff --git a/OneCprogsite/programmer/migrations/__pycache__/0001_initial.cpython-310.pyc b/OneCprogsite/programmer/migrations/__pycache__/0001_initial.cpython-310.pyc
deleted file mode 100644
index 09854a6..0000000
Binary files a/OneCprogsite/programmer/migrations/__pycache__/0001_initial.cpython-310.pyc and /dev/null differ
diff --git a/OneCprogsite/programmer/migrations/__pycache__/0002_alter_competence_options_alter_competence_content_and_more.cpython-310.pyc b/OneCprogsite/programmer/migrations/__pycache__/0002_alter_competence_options_alter_competence_content_and_more.cpython-310.pyc
deleted file mode 100644
index db34b31..0000000
Binary files a/OneCprogsite/programmer/migrations/__pycache__/0002_alter_competence_options_alter_competence_content_and_more.cpython-310.pyc and /dev/null differ
diff --git a/OneCprogsite/programmer/migrations/__pycache__/0003_recall_rename_is_publiched_competence_is_published.cpython-310.pyc b/OneCprogsite/programmer/migrations/__pycache__/0003_recall_rename_is_publiched_competence_is_published.cpython-310.pyc
deleted file mode 100644
index b43c27b..0000000
Binary files a/OneCprogsite/programmer/migrations/__pycache__/0003_recall_rename_is_publiched_competence_is_published.cpython-310.pyc and /dev/null differ
diff --git a/OneCprogsite/programmer/migrations/__pycache__/0004_rename_photo_recall_scan.cpython-310.pyc b/OneCprogsite/programmer/migrations/__pycache__/0004_rename_photo_recall_scan.cpython-310.pyc
deleted file mode 100644
index 474f4a1..0000000
Binary files a/OneCprogsite/programmer/migrations/__pycache__/0004_rename_photo_recall_scan.cpython-310.pyc and /dev/null differ
diff --git a/OneCprogsite/programmer/migrations/__pycache__/0005_auto_20231124_1519.cpython-310.pyc b/OneCprogsite/programmer/migrations/__pycache__/0005_auto_20231124_1519.cpython-310.pyc
deleted file mode 100644
index b626d01..0000000
Binary files a/OneCprogsite/programmer/migrations/__pycache__/0005_auto_20231124_1519.cpython-310.pyc and /dev/null differ
diff --git a/OneCprogsite/programmer/migrations/__pycache__/0006_alter_recall_scan.cpython-310.pyc b/OneCprogsite/programmer/migrations/__pycache__/0006_alter_recall_scan.cpython-310.pyc
deleted file mode 100644
index caac6b8..0000000
Binary files a/OneCprogsite/programmer/migrations/__pycache__/0006_alter_recall_scan.cpython-310.pyc and /dev/null differ
diff --git a/OneCprogsite/programmer/migrations/__pycache__/0007_solution.cpython-310.pyc b/OneCprogsite/programmer/migrations/__pycache__/0007_solution.cpython-310.pyc
deleted file mode 100644
index 90cdd6f..0000000
Binary files a/OneCprogsite/programmer/migrations/__pycache__/0007_solution.cpython-310.pyc and /dev/null differ
diff --git a/OneCprogsite/programmer/migrations/__pycache__/0008_home.cpython-310.pyc b/OneCprogsite/programmer/migrations/__pycache__/0008_home.cpython-310.pyc
deleted file mode 100644
index 20cebcb..0000000
Binary files a/OneCprogsite/programmer/migrations/__pycache__/0008_home.cpython-310.pyc and /dev/null differ
diff --git a/OneCprogsite/programmer/migrations/__pycache__/0009_callbackrequest_alter_competence_options.cpython-310.pyc b/OneCprogsite/programmer/migrations/__pycache__/0009_callbackrequest_alter_competence_options.cpython-310.pyc
deleted file mode 100644
index 2c3bab4..0000000
Binary files a/OneCprogsite/programmer/migrations/__pycache__/0009_callbackrequest_alter_competence_options.cpython-310.pyc and /dev/null differ
diff --git a/OneCprogsite/programmer/migrations/__pycache__/0010_alter_callbackrequest_email_and_more.cpython-310.pyc b/OneCprogsite/programmer/migrations/__pycache__/0010_alter_callbackrequest_email_and_more.cpython-310.pyc
deleted file mode 100644
index 165fc95..0000000
Binary files a/OneCprogsite/programmer/migrations/__pycache__/0010_alter_callbackrequest_email_and_more.cpython-310.pyc and /dev/null differ
diff --git a/OneCprogsite/programmer/migrations/__pycache__/0011_visitor_pageview.cpython-310.pyc b/OneCprogsite/programmer/migrations/__pycache__/0011_visitor_pageview.cpython-310.pyc
deleted file mode 100644
index b085443..0000000
Binary files a/OneCprogsite/programmer/migrations/__pycache__/0011_visitor_pageview.cpython-310.pyc and /dev/null differ
diff --git a/OneCprogsite/programmer/migrations/__pycache__/0012_callbackrequest_is_read.cpython-310.pyc b/OneCprogsite/programmer/migrations/__pycache__/0012_callbackrequest_is_read.cpython-310.pyc
deleted file mode 100644
index 342d187..0000000
Binary files a/OneCprogsite/programmer/migrations/__pycache__/0012_callbackrequest_is_read.cpython-310.pyc and /dev/null differ
diff --git a/OneCprogsite/programmer/migrations/__pycache__/0013_callbackrequest_notification_sent.cpython-310.pyc b/OneCprogsite/programmer/migrations/__pycache__/0013_callbackrequest_notification_sent.cpython-310.pyc
deleted file mode 100644
index 1bbd4b6..0000000
Binary files a/OneCprogsite/programmer/migrations/__pycache__/0013_callbackrequest_notification_sent.cpython-310.pyc and /dev/null differ
diff --git a/OneCprogsite/programmer/templatetags/__pycache__/programmer_tags.cpython-310.pyc b/OneCprogsite/programmer/templatetags/__pycache__/programmer_tags.cpython-310.pyc
deleted file mode 100644
index 2201004..0000000
Binary files a/OneCprogsite/programmer/templatetags/__pycache__/programmer_tags.cpython-310.pyc and /dev/null differ
diff --git a/OneCprogsite/programmer/templatetags/__pycache__/seo_tags.cpython-310.pyc b/OneCprogsite/programmer/templatetags/__pycache__/seo_tags.cpython-310.pyc
deleted file mode 100644
index b8da77a..0000000
Binary files a/OneCprogsite/programmer/templatetags/__pycache__/seo_tags.cpython-310.pyc and /dev/null differ
diff --git a/OneCprogsite/programmer/utils/__pycache__/email_notifications.cpython-310.pyc b/OneCprogsite/programmer/utils/__pycache__/email_notifications.cpython-310.pyc
deleted file mode 100644
index 12f89e7..0000000
Binary files a/OneCprogsite/programmer/utils/__pycache__/email_notifications.cpython-310.pyc and /dev/null differ
diff --git a/programmer/admin.py b/programmer/admin.py
index b2a1f5c..5962719 100644
--- a/programmer/admin.py
+++ b/programmer/admin.py
@@ -1,4 +1,3 @@
-<<<<<<< HEAD
from django.contrib import admin
from django.utils import timezone
from django.utils.html import format_html
@@ -168,174 +167,3 @@ admin.site.register(Competence, ProgrammerAdmin)
admin.site.register(Recall, RecallAdmin)
admin.site.register(Solution, SolutionAdmin)
admin.site.register(Home, HomeAdmin)
-=======
-from django.contrib import admin
-from django.utils import timezone
-from django.utils.html import format_html
-from django.urls import path
-from django.shortcuts import render
-from django.http import HttpResponseRedirect
-from django.contrib import messages
-from .models import *
-
-
-class ProgrammerAdmin(admin.ModelAdmin):
- list_display = ('id', 'title', 'time_create', 'photo', 'is_published')
- list_display_links = ('id', 'title')
- search_fields = ('title', 'content')
- list_editable = ('is_published',)
- list_filter = ('time_create', 'is_published')
-
-
-class RecallAdmin(admin.ModelAdmin):
- list_display = ('id', 'title', 'time_create', 'scan', 'is_published')
- list_display_links = ('id', 'title')
- search_fields = ('title', 'content')
- list_editable = ('is_published',)
- list_filter = ('time_create', 'is_published')
-
-
-class SolutionAdmin(admin.ModelAdmin):
- list_display = ('id', 'title', 'time_create', 'is_published')
- list_display_links = ('id', 'title')
- search_fields = ('title', 'description', 'implementation')
- list_editable = ('is_published',)
- list_filter = ('time_create', 'is_published')
-
-
-class HomeAdmin(admin.ModelAdmin):
- list_display = ('id', 'title', 'time_create', 'is_published')
- list_display_links = ('id', 'title')
- search_fields = ('title', 'content')
- list_editable = ('is_published',)
- list_filter = ('time_create', 'is_published')
-
-
-@admin.register(CallbackRequest)
-class CallbackAdmin(admin.ModelAdmin):
- list_display = ('name', 'phone', 'email', 'time_create', 'is_processed', 'is_read', 'new_badge')
- list_display_links = ('name', 'phone')
- list_editable = ('is_processed', 'is_read')
- list_filter = ('time_create', 'is_processed', 'is_read')
- search_fields = ('name', 'phone', 'email')
- readonly_fields = ('time_create',)
- actions = ['mark_as_read', 'mark_as_unread', 'mark_as_processed']
- actions = ['mark_as_read', 'mark_as_unread', 'mark_as_processed', 'resend_notification']
-
- def resend_notification(self, request, queryset):
- from .utils.email_notifications import send_callback_notification
- count = 0
- for callback in queryset:
- success = send_callback_notification(callback)
- if success:
- count += 1
- self.message_user(request, f'Уведомления отправлены для {count} заявок')
-
- resend_notification.short_description = "Переотправить email уведомления"
-
- def new_badge(self, obj):
- if not obj.is_read:
- return format_html('🆕 НОВАЯ')
- return ""
-
- new_badge.short_description = 'Статус'
-
- def get_queryset(self, request):
- # Показываем количество непрочитанных в заголовке
- unread_count = CallbackRequest.objects.filter(is_read=False).count()
- if unread_count > 0:
- self.message_user(
- request,
- f'У вас {unread_count} непрочитанных заявок!',
- messages.WARNING
- )
- return super().get_queryset(request)
-
- def mark_as_read(self, request, queryset):
- updated = queryset.update(is_read=True)
- self.message_user(request, f'{updated} заявок отмечены как прочитанные')
-
- mark_as_read.short_description = "Отметить как прочитанные"
-
- def mark_as_unread(self, request, queryset):
- updated = queryset.update(is_read=False)
- self.message_user(request, f'{updated} заявок отмечены как непрочитанные')
-
- mark_as_unread.short_description = "Отметить как непрочитанные"
-
- def mark_as_processed(self, request, queryset):
- updated = queryset.update(is_processed=True)
- self.message_user(request, f'{updated} заявок отмечены как обработанные')
-
- mark_as_processed.short_description = "Отметить как обработанные"
-
- # Добавляем кастомное представление для статистики
- def get_urls(self):
- urls = super().get_urls()
- custom_urls = [
- path('callback-stats/', self.admin_site.admin_view(self.callback_stats), name='callback_stats'),
- ]
- return custom_urls + urls
-
- def callback_stats(self, request):
- today = timezone.now().date()
- week_ago = today - timezone.timedelta(days=7)
-
- stats = {
- 'total': CallbackRequest.objects.count(),
- 'today': CallbackRequest.objects.filter(time_create__date=today).count(),
- 'week': CallbackRequest.objects.filter(time_create__date__gte=week_ago).count(),
- 'unread': CallbackRequest.objects.filter(is_read=False).count(),
- 'unprocessed': CallbackRequest.objects.filter(is_processed=False).count(),
- }
-
- context = {
- **self.admin_site.each_context(request),
- 'title': 'Статистика заявок',
- 'stats': stats,
- }
- return render(request, 'admin/callback_stats.html', context)
-
-class ProgrammerAdmin(admin.ModelAdmin):
- list_display = ('id', 'title', 'time_create', 'photo', 'is_published')
- list_display_links = ('id', 'title')
- search_fields = ('title', 'content')
- list_editable = ('is_published',)
- list_filter = ('time_create', 'is_published')
-
-class RecallAdmin(admin.ModelAdmin):
- list_display = ('id', 'title', 'time_create', 'scan', 'is_published')
- list_display_links = ('id', 'title')
- search_fields = ('title', 'content')
- list_editable = ('is_published',)
- list_filter = ('time_create', 'is_published')
-
-class SolutionAdmin(admin.ModelAdmin):
- list_display = ('id', 'title', 'time_create', 'is_published')
- list_display_links = ('id', 'title')
- search_fields = ('title', 'description', 'implementation')
- list_editable = ('is_published',)
- list_filter = ('time_create', 'is_published')
-
-class HomeAdmin(admin.ModelAdmin):
- list_display = ('id', 'title', 'time_create', 'is_published')
- list_display_links = ('id', 'title')
- search_fields = ('title', 'content')
- list_editable = ('is_published',)
- list_filter = ('time_create', 'is_published')
-
-@admin.register(PageView)
-class PageViewAdmin(admin.ModelAdmin):
- list_display = ['url', 'timestamp', 'ip_address']
- list_filter = ['timestamp', 'url']
- search_fields = ['url', 'ip_address']
- date_hierarchy = 'timestamp'
-
- def get_queryset(self, request):
- return super().get_queryset(request).order_by('-timestamp')
-
-admin.site.register(Competence, ProgrammerAdmin)
-admin.site.register(Recall, RecallAdmin)
-admin.site.register(Solution, SolutionAdmin)
-admin.site.register(Home, HomeAdmin)
->>>>>>> master
diff --git a/programmer/apps.py b/programmer/apps.py
index c2c4ad0..c8b6481 100644
--- a/programmer/apps.py
+++ b/programmer/apps.py
@@ -1,4 +1,3 @@
-<<<<<<< HEAD
from django.apps import AppConfig
@@ -6,12 +5,3 @@ class ProgrammerConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'programmer'
verbose_name = 'Программисты'
-=======
-from django.apps import AppConfig
-
-
-class ProgrammerConfig(AppConfig):
- default_auto_field = 'django.db.models.BigAutoField'
- name = 'programmer'
- verbose_name = 'Программисты'
->>>>>>> master
diff --git a/programmer/context_processors.py b/programmer/context_processors.py
index 7261401..41a7d3c 100644
--- a/programmer/context_processors.py
+++ b/programmer/context_processors.py
@@ -1,4 +1,3 @@
-<<<<<<< HEAD
from .views import menu
from django.conf import settings
@@ -10,17 +9,4 @@ def contact_info(request):
return {
'CONTACT_EMAIL': getattr(settings, 'CONTACT_EMAIL', 'it@nserdyuk.ru'),
'CONTACT_PHONE': getattr(settings, 'CONTACT_PHONE', '+7 (960) 469-40-88'),
-=======
-from .views import menu
-from django.conf import settings
-
-
-def menu_processor(request):
- return {'menu': menu}
-
-def contact_info(request):
- return {
- 'CONTACT_EMAIL': getattr(settings, 'CONTACT_EMAIL', 'it@nserdyuk.ru'),
- 'CONTACT_PHONE': getattr(settings, 'CONTACT_PHONE', '+7 (960) 469-40-88'),
->>>>>>> master
}
\ No newline at end of file
diff --git a/programmer/forms.py b/programmer/forms.py
index 9023bc1..9726b2c 100644
--- a/programmer/forms.py
+++ b/programmer/forms.py
@@ -1,4 +1,3 @@
-<<<<<<< HEAD
from django import forms
from .models import CallbackRequest
@@ -31,38 +30,4 @@ class CallbackForm(forms.ModelForm):
'phone': 'Телефон',
'email': 'Электронная почта',
'question': 'Ваш вопрос'
-=======
-from django import forms
-from .models import CallbackRequest
-
-
-class CallbackForm(forms.ModelForm):
- class Meta:
- model = CallbackRequest
- fields = ['name', 'phone', 'email', 'question']
- widgets = {
- 'name': forms.TextInput(attrs={
- 'class': 'form-input',
- 'placeholder': 'Ваше имя'
- }),
- 'phone': forms.TextInput(attrs={
- 'class': 'form-input',
- 'placeholder': '+7 (___) ___-__-__'
- }),
- 'email': forms.EmailInput(attrs={
- 'class': 'form-input',
- 'placeholder': 'your@email.com'
- }),
- 'question': forms.Textarea(attrs={
- 'class': 'form-textarea',
- 'placeholder': 'Опишите ваш вопрос или задачу...',
- 'rows': 4
- }),
- }
- labels = {
- 'name': 'Имя',
- 'phone': 'Телефон',
- 'email': 'Электронная почта',
- 'question': 'Ваш вопрос'
->>>>>>> master
}
\ No newline at end of file
diff --git a/programmer/middleware.py b/programmer/middleware.py
index 98e272c..494461e 100644
--- a/programmer/middleware.py
+++ b/programmer/middleware.py
@@ -1,4 +1,3 @@
-<<<<<<< HEAD
from .models import PageView, Visitor
from django.utils import timezone
from django.db import transaction
@@ -52,59 +51,4 @@ class PageViewMiddleware:
ip = x_forwarded_for.split(',')[0]
else:
ip = request.META.get('REMOTE_ADDR')
-=======
-from .models import PageView, Visitor
-from django.utils import timezone
-from django.db import transaction
-
-
-class PageViewMiddleware:
- def __init__(self, get_response):
- self.get_response = get_response
-
- def __call__(self, request):
- # Игнорируем статические файлы и админку
- if not request.path.startswith('/static/') and not request.path.startswith('/admin/'):
- self.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')
->>>>>>> master
return ip
\ No newline at end of file
diff --git a/programmer/models.py b/programmer/models.py
index e07c9a6..b62f79b 100644
--- a/programmer/models.py
+++ b/programmer/models.py
@@ -1,159 +1,3 @@
-<<<<<<< HEAD
-from django.db import models
-from django.urls import reverse
-from django.utils import timezone
-from django.db.models.signals import post_save, post_delete
-from django.dispatch import receiver
-from django.core.cache import cache
-from .utils.email_notifications import send_callback_notification
-
-
-class Recall(models.Model):
- title = models.CharField(max_length=255, verbose_name='Организация')
- content = models.TextField(blank=True, verbose_name='Отзыв')
- scan = models.ImageField(upload_to="scan/%Y/%m/%d/", verbose_name='Фото')
- time_create = models.DateTimeField(auto_now_add=True, verbose_name='Дата создания')
- time_update = models.DateTimeField(auto_now=True, verbose_name='Дата изменения')
- is_published = models.BooleanField(default=True, verbose_name='Опубликован')
-
- def __str__(self):
- return self.title
-
- def get_absolute_url(self):
- return reverse('post', kwargs={'post_id': self.pk})
-
- class Meta:
- verbose_name = 'Отзыв'
- verbose_name_plural = 'Отзывы'
- ordering = ['time_create', 'title']
-
-
-class Competence(models.Model):
- title = models.CharField(max_length=255, verbose_name='Программист')
- content = models.TextField(blank=True, verbose_name='Компетенция')
- photo = models.ImageField(upload_to="photos/%Y/%m/%d/", verbose_name='Фото')
- time_create = models.DateTimeField(auto_now_add=True, verbose_name='Дата создания')
- time_update = models.DateTimeField(auto_now=True, verbose_name='Дата изменения')
- is_published = models.BooleanField(default=True, verbose_name='Опубликован')
-
- def __str__(self):
- return self.title
-
- def get_absolute_url(self):
- return reverse('post', kwargs={'post_id': self.pk})
-
- class Meta:
- verbose_name = 'Компетенция'
- verbose_name_plural = 'Компетенции'
- ordering = ['time_create', 'title']
-
-
-class Solution(models.Model):
- title = models.CharField(max_length=255, verbose_name='Наименование')
- description = models.TextField(blank=True, verbose_name='Описание')
- implementation = models.TextField(blank=True, verbose_name='Реализация')
- closing = models.TextField(blank=True, verbose_name='Заключение')
- time_create = models.DateTimeField(auto_now_add=True, verbose_name='Дата создания')
- time_update = models.DateTimeField(auto_now=True, verbose_name='Дата изменения')
- is_published = models.BooleanField(default=True, verbose_name='Опубликован')
-
- def __str__(self):
- return self.title
-
- def get_absolute_url(self):
- return reverse('post', kwargs={'post_id': self.pk})
-
- class Meta:
- verbose_name = 'Проекты'
- verbose_name_plural = 'Проекты'
- ordering = ['time_create', 'title']
-
-
-class Home(models.Model):
- title = models.CharField(max_length=255, verbose_name='Наименование')
- content = models.TextField(blank=True, verbose_name='Статья')
- home_image = models.ImageField(upload_to="home_image/%Y/%m/%d/", verbose_name='Фото')
- time_create = models.DateTimeField(auto_now_add=True, verbose_name='Дата создания')
- time_update = models.DateTimeField(auto_now=True, verbose_name='Дата изменения')
- is_published = models.BooleanField(default=True, verbose_name='Опубликован')
-
- def __str__(self):
- return self.title
-
- def get_absolute_url(self):
- return reverse('post', kwargs={'post_id': self.pk})
-
- class Meta:
- verbose_name = 'Главная страница'
- verbose_name_plural = 'Главная страница'
- ordering = ['time_create', 'title']
-
-
-class CallbackRequest(models.Model):
- name = models.CharField(max_length=100, verbose_name='Имя')
- phone = models.CharField(max_length=20, verbose_name='Телефон')
- email = models.EmailField(blank=True, null=True, verbose_name='Электронная почта') # Сделать необязательным
- question = models.TextField(blank=True, verbose_name='Ваш вопрос') # Сделать необязательным
- time_create = models.DateTimeField(auto_now_add=True, verbose_name='Дата создания')
- is_processed = models.BooleanField(default=False, verbose_name='Обработано')
- is_read = models.BooleanField(default=False, verbose_name='Прочитано')
- notification_sent = models.BooleanField(default=False, verbose_name='Уведомление отправлено')
-
- def __str__(self):
- return f"{self.name} - {self.phone}"
-
- class Meta:
- verbose_name = 'Заявка на звонок'
- verbose_name_plural = 'Заявки на звонок'
- ordering = ['-time_create']
-
-
-# Сигнал для отправки уведомления при создании заявки
-@receiver(post_save, sender=CallbackRequest)
-def send_callback_email_notification(sender, instance, created, **kwargs):
- if created and not instance.notification_sent:
- # Отправляем email уведомление
- success = send_callback_notification(instance)
- if success:
- instance.notification_sent = True
- # Сохраняем без повторного вызова сигнала
- sender.objects.filter(pk=instance.pk).update(notification_sent=True)
-
-
-class PageView(models.Model):
- url = models.CharField(max_length=500)
- timestamp = models.DateTimeField(default=timezone.now)
- ip_address = models.GenericIPAddressField()
- user_agent = models.TextField(blank=True)
- referer = models.CharField(max_length=500, blank=True)
-
- class Meta:
- indexes = [
- models.Index(fields=['url', 'timestamp']),
- models.Index(fields=['timestamp']),
- ]
-
-
-class Visitor(models.Model):
- ip_address = models.GenericIPAddressField()
- first_visit = models.DateTimeField(default=timezone.now)
- last_visit = models.DateTimeField(default=timezone.now)
- visit_count = models.IntegerField(default=1)
-
- class Meta:
- indexes = [
- models.Index(fields=['ip_address']),
- ]
-
-
-@receiver([post_save, post_delete], sender=Home)
-@receiver([post_save, post_delete], sender=Solution)
-@receiver([post_save, post_delete], sender=Competence)
-@receiver([post_save, post_delete], sender=Recall)
-def clear_sitemap_cache(sender, **kwargs):
- """Очищаем кэш sitemap при изменении контента"""
- cache.delete('sitemap_cache')
-=======
from django.db import models
from django.urls import reverse
from django.utils import timezone
@@ -334,4 +178,3 @@ class Visitor(models.Model):
def clear_sitemap_cache(sender, **kwargs):
"""Очищаем кэш sitemap при изменении контента"""
cache.delete('sitemap_cache')
->>>>>>> master
diff --git a/programmer/sitemaps.py b/programmer/sitemaps.py
index 16fe364..e71f587 100644
--- a/programmer/sitemaps.py
+++ b/programmer/sitemaps.py
@@ -1,4 +1,3 @@
-<<<<<<< HEAD
from django.contrib.sitemaps import Sitemap
from django.urls import reverse
from .models import Home, Solution, Competence, Recall
@@ -62,69 +61,4 @@ sitemaps = {
'solutions': SolutionSitemap,
'competence': CompetenceSitemap,
'recall': RecallSitemap,
-=======
-from django.contrib.sitemaps import Sitemap
-from django.urls import reverse
-from .models import Home, Solution, Competence, Recall
-
-class StaticViewSitemap(Sitemap):
- priority = 1.0
- changefreq = 'monthly'
-
- def items(self):
- return ['home', 'about', 'solution', 'ability', 'recall']
-
- def location(self, item):
- return reverse(item)
-
-class HomeSitemap(Sitemap):
- changefreq = 'weekly'
- priority = 1.0
-
- def items(self):
- return Home.objects.filter(is_published=True)
-
- def lastmod(self, obj):
- return obj.time_update
-
- # УБИРАЕМ метод location - используем default
- # Django автоматически сгенерирует правильные URL
-
-class SolutionSitemap(Sitemap):
- changefreq = 'weekly'
- priority = 0.9
-
- def items(self):
- return Solution.objects.filter(is_published=True)
-
- def lastmod(self, obj):
- return obj.time_update
-
-class CompetenceSitemap(Sitemap):
- changefreq = 'monthly'
- priority = 0.8
-
- def items(self):
- return Competence.objects.filter(is_published=True)
-
- def lastmod(self, obj):
- return obj.time_update
-
-class RecallSitemap(Sitemap):
- changefreq = 'monthly'
- priority = 0.7
-
- def items(self):
- return Recall.objects.filter(is_published=True)
-
- def lastmod(self, obj):
- return obj.time_update
-
-# Упрощаем sitemaps - убираем HomeSitemap если он дублирует главную
-sitemaps = {
- 'static': StaticViewSitemap,
- 'solutions': SolutionSitemap,
- 'competence': CompetenceSitemap,
- 'recall': RecallSitemap,
->>>>>>> master
}
\ No newline at end of file
diff --git a/programmer/templates/admin/base.html b/programmer/templates/admin/base.html
index 42d2eb0..c8f00f5 100644
--- a/programmer/templates/admin/base.html
+++ b/programmer/templates/admin/base.html
@@ -1,4 +1,3 @@
-<<<<<<< HEAD
@@ -77,84 +76,4 @@
{% bootstrap_javascript %}
-=======
-
-
-
-
-
- {% block title %}Админ-панель - Статистика{% endblock %}
- {% load django_bootstrap5 %}
- {% bootstrap_css %}
-
-
-
-
-
-
- {% bootstrap_messages %}
- {% block content %}
- {% endblock %}
-
-
- {% bootstrap_javascript %}
-
->>>>>>> master
\ No newline at end of file
diff --git a/programmer/templates/admin/base_site.html b/programmer/templates/admin/base_site.html
index 5481d79..58bd451 100644
--- a/programmer/templates/admin/base_site.html
+++ b/programmer/templates/admin/base_site.html
@@ -1,4 +1,3 @@
-<<<<<<< HEAD
{% extends "admin/base.html" %}
{% block title %}{{ title }} | {{ site_title|default:_('Django site admin') }}{% endblock %}
@@ -24,31 +23,4 @@
📊 Статистика заявок /
📈 Посещения /
{{ block.super }}
-=======
-{% extends "admin/base.html" %}
-
-{% block title %}{{ title }} | {{ site_title|default:_('Django site admin') }}{% endblock %}
-
-{% block branding %}
-
-{% endblock %}
-
-{% block nav-global %}
-{% endblock %}
-
-{% block userlinks %}
- {% load programmer_tags %}
-
-
- {% get_unread_callbacks as unread_callbacks %}
- {% if unread_callbacks %}
-
- 🚨 {{ unread_callbacks }} новых заявок
- /
- {% endif %}
-
- 📊 Статистика заявок /
- 📈 Посещения /
- {{ block.super }}
->>>>>>> master
{% endblock %}
\ No newline at end of file
diff --git a/programmer/templates/admin/callback_stats.html b/programmer/templates/admin/callback_stats.html
index 9845dd7..916c167 100644
--- a/programmer/templates/admin/callback_stats.html
+++ b/programmer/templates/admin/callback_stats.html
@@ -1,4 +1,3 @@
-<<<<<<< HEAD
{% extends "admin/base_site.html" %}
{% block title %}Статистика заявок{% endblock %}
@@ -43,50 +42,4 @@
-=======
-{% extends "admin/base_site.html" %}
-
-{% block title %}Статистика заявок{% endblock %}
-
-{% block content %}
-
-
📊 Статистика заявок на обратный звонок
-
-
-
-
📋 Всего заявок
-
{{ stats.total }}
-
-
-
-
📅 Сегодня
-
{{ stats.today }}
-
-
-
-
📈 За неделю
-
{{ stats.week }}
-
-
-
-
🆕 Непрочитанные
-
{{ stats.unread }}
-
-
-
-
⏳ В обработке
-
{{ stats.unprocessed }}
-
-
-
-
-
->>>>>>> master
{% endblock %}
\ No newline at end of file
diff --git a/programmer/templates/admin/statistics.html b/programmer/templates/admin/statistics.html
index f0f8643..4a1650d 100644
--- a/programmer/templates/admin/statistics.html
+++ b/programmer/templates/admin/statistics.html
@@ -1,4 +1,3 @@
-<<<<<<< HEAD
{% extends 'admin/base.html' %}
{% load programmer_tags %}
@@ -129,136 +128,4 @@
-=======
-{% extends 'admin/base.html' %}
-{% load programmer_tags %}
-
-{% block title %}Статистика посещений{% endblock %}
-{% block page_title %}Статистика посещений{% endblock %}
-
-{% block content %}
-
-{% get_unread_callbacks as unread_callbacks %}
-{% get_today_callbacks as today_callbacks %}
-{% if unread_callbacks > 0 %}
-
-
🚨 Внимание!
-
- У вас {{ unread_callbacks }} непрочитанных заявок на обратный звонок
- {% if today_callbacks > 0 %}
- ({{ today_callbacks }} из них сегодня)
- {% endif %}
-
-
- 📋 Перейти к заявкам
-
-
-
-{% endif %}
-
-
-
-
-
-
📊 Просмотров сегодня
-
{{ today_views }}
-
-
-
📈 Просмотров за неделю
-
{{ weekly_views }}
-
-
-
👥 Уникальных посетителей
-
{{ unique_visitors }}
-
-
-
🕒 Всего просмотров
-
{{ total_views }}
-
-
-
-
📞 Заявок сегодня
-
{{ today_callbacks }}
-
-
-
📋 Всего заявок
-
{% get_unread_callbacks %}/{{ total_callbacks }}
-
(непрочитанные/всего)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- | Страница |
- Просмотров |
-
-
-
- {% for page in popular_pages %}
-
-
- {{ page.url }}
- {% if page.url == '/' %}
- Главная
- {% endif %}
- |
- {{ page.views }} |
-
- {% empty %}
-
- | Нет данных за выбранный период |
-
- {% endfor %}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- | Время |
- Страница |
- IP-адрес |
-
-
-
- {% for view in recent_views %}
-
- | {{ view.timestamp|date:"d.m.Y H:i" }} |
- {{ view.url }} |
- {{ view.ip_address }} |
-
- {% empty %}
-
- | Нет данных |
-
- {% endfor %}
-
-
-
-
-
-
->>>>>>> master
{% endblock %}
\ No newline at end of file
diff --git a/programmer/templates/emails/callback_notification.html b/programmer/templates/emails/callback_notification.html
index e91be02..4e7cdd8 100644
--- a/programmer/templates/emails/callback_notification.html
+++ b/programmer/templates/emails/callback_notification.html
@@ -1,4 +1,3 @@
-<<<<<<< HEAD
@@ -55,62 +54,4 @@
-=======
-
-
-
-
-
-
-
-
-
-
-
-
-
- ⚠️ Срочно! Пользователь оставил заявку на обратный звонок.
-
-
-
-
📋 Информация о заявке:
-
👤 Имя: {{ callback.name }}
-
📞 Телефон: {{ callback.phone }}
- {% if callback.email %}
-
📧 Email: {{ callback.email }}
- {% endif %}
- {% if callback.question %}
-
❓ Вопрос:
{{ callback.question }}
- {% endif %}
-
🕒 Время отправки: {{ callback.time_create|date:"d.m.Y H:i" }}
-
-
-
-
-
Не забудьте отметить заявку как обработанную после связи с клиентом!
-
-
-
-
-
->>>>>>> master
\ No newline at end of file
diff --git a/programmer/templates/emails/daily_summary.html b/programmer/templates/emails/daily_summary.html
index 86d307d..7886975 100644
--- a/programmer/templates/emails/daily_summary.html
+++ b/programmer/templates/emails/daily_summary.html
@@ -1,4 +1,3 @@
-<<<<<<< HEAD
@@ -58,65 +57,4 @@
-=======
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
📅 Вчерашние заявки
-
{{ yesterday_callbacks }}
-
-
-
-
⏳ Ожидают обработки
-
{{ unprocessed_callbacks }}
-
-
-
- {% if unprocessed_callbacks > 0 %}
-
- ⚠️ Внимание! У вас есть {{ unprocessed_callbacks }} необработанных заявок.
-
- {% endif %}
-
-
-
-
Не забудьте обработать все pending заявки!
-
-
-
-
-
->>>>>>> master
\ No newline at end of file
diff --git a/programmer/templates/programmer/about.html b/programmer/templates/programmer/about.html
index 1515dd4..696fa6d 100644
--- a/programmer/templates/programmer/about.html
+++ b/programmer/templates/programmer/about.html
@@ -1,4 +1,3 @@
-<<<<<<< HEAD
{% extends 'programmer/base.html' %}
{% load django_bootstrap5 %}
@@ -152,159 +151,4 @@
}
-=======
-{% extends 'programmer/base.html' %}
-{% load django_bootstrap5 %}
-
-{% block content %}
-
-
-
-
-
-
-
🚀 Опыт работы
-
Более 10 лет успешной работы в разработке и сопровождении систем на платформе 1С
-
-
-
Основные направления:
-
-
-
💻 Разработка
-
- - Разработка и доработка конфигураций 1С
- - Создание внешних обработок и отчетов
- - Кастомизация под бизнес-процессы
-
-
-
-
🔗 Интеграция
-
- - Интеграция 1С с веб-сервисами
- - Связь с сайтами и мобильными приложениями
- - API и веб-сервисы
-
-
-
-
⚡ Оптимизация
-
- - Оптимизация бизнес-процессов
- - Ускорение работы баз данных
- - Автоматизация рутинных операций
-
-
-
-
-
-
-
-
🛠 Технологии и навыки
-
-
-
🎯 1С Разработка
-
- - 1С:Предприятие 8.3
- - Управление торговлей
- - Бухгалтерия предприятия
- - Зарплата и управление персоналом
- - Внешние обработки и отчеты
-
-
-
-
🔧 Дополнительные технологии
-
- - SQL и оптимизация запросов
- - Веб-сервисы и API
- - XML, JSON, REST
- - Системное администрирование
-
-
-
-
-
-
-
📈 Проекты и достижения
-
Успешно реализовал более 50 проектов различной сложности
-
-
-
-
🏆 Ключевые проекты
-
- - Автоматизация учетных систем для предприятий
- - Интеграция 1С с сайтами и мобильными приложениями
- - Разработка кастомизированных отчетов и дашбордов
- - Оптимизация производительности баз данных
-
-
-
-
-
-
-
-
-
-
-
-
->>>>>>> master
{% endblock %}
\ No newline at end of file
diff --git a/programmer/templates/programmer/base.html b/programmer/templates/programmer/base.html
index 933f594..ff10cda 100644
--- a/programmer/templates/programmer/base.html
+++ b/programmer/templates/programmer/base.html
@@ -1,559 +1,3 @@
-<<<<<<< HEAD
-{% load static %}
-{% load programmer_tags %}
-{% load django_bootstrap5 %}
-
-
-
- {{title}} - Программист 1С
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {% bootstrap_css %}
-
-
-
-
-
-
-
-
-
-
-
- {% block extra_css %}
-
- {% endblock %}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {% block mainmenu %}
-
-
-
-
-
- {% endblock mainmenu %}
-
-
-
-
-
-
- {% block breadcrumbs %}
-
- {% endblock %}
-
-
- {% bootstrap_messages %}
-
-
-
- {% block content %}
- {% endblock %}
-
-
-
-
-
-
-
-
- {% bootstrap_javascript %}
-
-
-
- {% block extra_js %}
-
- {% endblock %}
-
-=======
{% load static %}
{% load programmer_tags %}
{% load django_bootstrap5 %}
@@ -1131,5 +575,4 @@
}
->>>>>>> master
\ No newline at end of file
diff --git a/programmer/templates/programmer/callback.html b/programmer/templates/programmer/callback.html
index 7528544..9106615 100644
--- a/programmer/templates/programmer/callback.html
+++ b/programmer/templates/programmer/callback.html
@@ -1,4 +1,3 @@
-<<<<<<< HEAD
{% extends 'programmer/base.html' %}
{% load django_bootstrap5 %}
@@ -6,13 +5,4 @@
-=======
-{% extends 'programmer/base.html' %}
-{% load django_bootstrap5 %}
-
-{% block content %}
-
-
-
->>>>>>> master
{% endblock %}
\ No newline at end of file
diff --git a/programmer/templates/programmer/competence.html b/programmer/templates/programmer/competence.html
index 19e565f..2c261b5 100644
--- a/programmer/templates/programmer/competence.html
+++ b/programmer/templates/programmer/competence.html
@@ -1,76 +1,3 @@
-<<<<<<< HEAD
-{% extends 'programmer/base.html' %}
-{% load django_bootstrap5 %}
-{% load static %}
-
-{% block extra_css %}
-
-{% endblock %}
-
-{% block content %}
-
-
-
- {% for p in posts %}
-
-
- {% if p.photo %}
-
-
-

-
- 🔍
- Нажмите для увеличения
-
-
-
- {% endif %}
-
-
-
{{ p.title }}
-
- {{ p.content|linebreaks }}
-
-
-
-
- {% endfor %}
-
-
-{% if not posts %}
-
-
📚 Информация о компетенциях
-
Раздел находится в разработке
-
-
-{% endif %}
-
-
-
-
-
-
-
![Увеличенное изображение компетенции]()
-
-
-
-{% endblock %}
-
-{% block extra_js %}
-
-=======
{% extends 'programmer/base.html' %}
{% load django_bootstrap5 %}
{% load static %}
@@ -142,5 +69,4 @@
{% block extra_js %}
->>>>>>> master
{% endblock %}
\ No newline at end of file
diff --git a/programmer/templates/programmer/humans.txt b/programmer/templates/programmer/humans.txt
index c32412e..7a8f4bc 100644
--- a/programmer/templates/programmer/humans.txt
+++ b/programmer/templates/programmer/humans.txt
@@ -1,4 +1,3 @@
-<<<<<<< HEAD
/* TEAM */
Developer: Николай Сердюк
Site: https://nikdizell.ru
@@ -11,18 +10,4 @@ Bootstrap
/* SITE */
Last update: 2025
Language: Russian
-=======
-/* TEAM */
-Developer: Николай Сердюк
-Site: https://nikdizell.ru
-Email: {{ CONTACT_EMAIL }}
-
-/* THANKS */
-Django Framework
-Bootstrap
-
-/* SITE */
-Last update: 2025
-Language: Russian
->>>>>>> master
Doctype: HTML5
\ No newline at end of file
diff --git a/programmer/templates/programmer/index.html b/programmer/templates/programmer/index.html
index 8539a39..ca59bd6 100644
--- a/programmer/templates/programmer/index.html
+++ b/programmer/templates/programmer/index.html
@@ -1,4 +1,3 @@
-<<<<<<< HEAD
{% extends 'programmer/base.html' %}
{% load django_bootstrap5 %}
@@ -101,108 +100,4 @@ document.addEventListener('keydown', function(event) {
}
});
-=======
-{% extends 'programmer/base.html' %}
-{% load django_bootstrap5 %}
-
-{% block content %}
-
-
🚀 Добро пожаловать!
-
Я профессиональный программист 1С с опытом создания эффективных бизнес-решений
-
-
-
- {% autoescape off %}
- {% for p in posts %}
-
-
-
- {{p.content}}
-
-
-
-
-
- {% endfor %}
- {% endautoescape %}
-
-
-
-
-
-{% if not posts %}
-
-
🚀 Контент скоро появится
-
Мы готовим для вас интересные материалы и кейсы
-
-
-
-
-{% endif %}
-
-
->>>>>>> master
{% endblock %}
\ No newline at end of file
diff --git a/programmer/templates/programmer/recall.html b/programmer/templates/programmer/recall.html
index 83a4b8f..faca463 100644
--- a/programmer/templates/programmer/recall.html
+++ b/programmer/templates/programmer/recall.html
@@ -1,153 +1,3 @@
-<<<<<<< HEAD
-{% extends 'programmer/base.html' %}
-{% load django_bootstrap5 %}
-{% load static %}
-
-{% block extra_css %}
-
-{% endblock %}
-
-{% block content %}
-
-
-
- {% for p in posts %}
-
-
-
-
-
- {% if p.scan %}
-
-
-

-
- 🔍
- Нажмите для увеличения
-
-
-
- {% endif %}
-
-
- {{ p.content|linebreaks }}
-
-
-
-
- {% endfor %}
-
-
-{% if not posts %}
-
-
💬 Отзывы клиентов
-
Здесь будут отображаться отзывы от довольных клиентов
-
-
-{% endif %}
-
-
-
-
-
-
-
![]()
-
-
-
-
-
-=======
{% extends 'programmer/base.html' %}
{% load django_bootstrap5 %}
{% load static %}
@@ -321,5 +171,4 @@ function adjustModalImageSize() {
{% block extra_js %}
->>>>>>> master
{% endblock %}
\ No newline at end of file
diff --git a/programmer/templates/programmer/robots.txt b/programmer/templates/programmer/robots.txt
index 437205e..32d69b7 100644
--- a/programmer/templates/programmer/robots.txt
+++ b/programmer/templates/programmer/robots.txt
@@ -1,22 +1,3 @@
-<<<<<<< HEAD
-User-agent: *
-Allow: /
-
-# Основной сайт
-Sitemap: {{ request.scheme }}://{{ request.get_host }}/sitemap.xml
-
-# Запрещаем служебные разделы
-Disallow: /admin/
-Disallow: /static/admin/
-Disallow: /callback/
-Disallow: /api/
-
-# Разрешаем индексацию статических файлов
-Allow: /static/
-Allow: /media/
-
-# Указываем главное зеркало
-=======
User-agent: *
Allow: /
@@ -35,5 +16,4 @@ Allow: /static/
Allow: /media/
# Указываем главное зеркало
->>>>>>> master
Host: {{ request.scheme }}://{{ request.get_host }}
\ No newline at end of file
diff --git a/programmer/templates/programmer/sitemap.xml b/programmer/templates/programmer/sitemap.xml
index fe18a95..62e1b06 100644
--- a/programmer/templates/programmer/sitemap.xml
+++ b/programmer/templates/programmer/sitemap.xml
@@ -1,4 +1,3 @@
-<<<<<<< HEAD
@@ -10,17 +9,4 @@
{% if url.priority %}{{ url.priority }}{% endif %}
{% endfor %}
-=======
-
-
-{% for url in urlset %}
-
- {{ url.location }}
- {% if url.lastmod %}{{ url.lastmod|date:"Y-m-d" }}{% endif %}
- {% if url.changefreq %}{{ url.changefreq }}{% endif %}
- {% if url.priority %}{{ url.priority }}{% endif %}
-
-{% endfor %}
->>>>>>> master
\ No newline at end of file
diff --git a/programmer/templates/programmer/solution.html b/programmer/templates/programmer/solution.html
index e184af4..babc513 100644
--- a/programmer/templates/programmer/solution.html
+++ b/programmer/templates/programmer/solution.html
@@ -1,74 +1,3 @@
-<<<<<<< HEAD
-{% extends 'programmer/base.html' %}
-{% load django_bootstrap5 %}
-{% load static %}
-
-{% block extra_css %}
-
-{% endblock %}
-
-{% block content %}
-{{title}}
-
-
- {% autoescape off %}
- {% for p in posts %}
-
-
-
{{p.title}}
-
-
-
-
-
- {{p.description}}
-
-
-
-
-
-
- {{p.implementation}}
-
-
-
-
-
-
-
-
Опубликовано: {{p.time_create|date:"d.m.Y"}}
-
-
-
- {% endfor %}
- {% endautoescape %}
-
-
-{% if not posts %}
-
-
Примеры решений скоро появятся
-
Мы готовим для вас интересные кейсы и решения
-
-{% endif %}
-
-
-
-
-=======
{% extends 'programmer/base.html' %}
{% load django_bootstrap5 %}
{% load static %}
@@ -164,5 +93,4 @@
->>>>>>> master
{% endblock %}
\ No newline at end of file
diff --git a/programmer/templatetags/programmer_tags.py b/programmer/templatetags/programmer_tags.py
index 67afdc1..b7b1498 100644
--- a/programmer/templatetags/programmer_tags.py
+++ b/programmer/templatetags/programmer_tags.py
@@ -1,19 +1,3 @@
-<<<<<<< HEAD
-from django import template
-from programmer.models import *
-
-
-register = template.Library()
-
-@register.simple_tag(name='competence')
-def get_competence():
- return Competence.objects.all()
-
-
-@register.simple_tag(name='recall')
-def get_recall():
- return Recall.objects.all()
-=======
from django import template
from ..models import CallbackRequest
@@ -28,4 +12,3 @@ def get_today_callbacks():
from django.utils import timezone
today = timezone.now().date()
return CallbackRequest.objects.filter(time_create__date=today).count()
->>>>>>> master
diff --git a/programmer/tests.py b/programmer/tests.py
index 0e7885b..7ce503c 100644
--- a/programmer/tests.py
+++ b/programmer/tests.py
@@ -1,9 +1,3 @@
-<<<<<<< HEAD
from django.test import TestCase
# Create your tests here.
-=======
-from django.test import TestCase
-
-# Create your tests here.
->>>>>>> master
diff --git a/programmer/urls.py b/programmer/urls.py
index 0547193..ed69c18 100644
--- a/programmer/urls.py
+++ b/programmer/urls.py
@@ -1,4 +1,3 @@
-<<<<<<< HEAD
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
@@ -25,32 +24,4 @@ urlpatterns = [
if settings.DEBUG:
-=======
-from django.contrib import admin
-from django.urls import path, include
-from django.conf import settings
-from django.conf.urls.static import static
-from .views import *
-from django.contrib.sitemaps.views import sitemap
-from .sitemaps import sitemaps
-
-
-urlpatterns = [
- path('', index, name='home'),
- path('about/', about, name='about'),
- path('solutions/', solution, name='solution'),
- path('competence/', ability, name='ability'),
- path('recall/', recall, name='recall'),
- path('post//', show_post, name='post'),
- path('callback/', callback_request, name='callback'),
- path('admin/statistics/', statistics_view, name='statistics'),
- # Sitemap
- path('sitemap.xml', sitemap, {'sitemaps': sitemaps},
- name='django.contrib.sitemaps.views.sitemap'),
- path('robots.txt', robots_txt, name='robots'),
-]
-
-
-if settings.DEBUG:
->>>>>>> master
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
\ No newline at end of file
diff --git a/programmer/views.py b/programmer/views.py
index 7601fe6..999b213 100644
--- a/programmer/views.py
+++ b/programmer/views.py
@@ -1,258 +1,3 @@
-<<<<<<< HEAD
-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': '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': "Главная страница",
- 'meta_description': "Профессиональный программист 1С с более чем 10-летним опытом. Разработка, интеграция и оптимизация систем 1С. Закажите консультацию.",
- 'meta_keywords': "программист 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С",
- 'meta_description': "Николай Сердюк - профессиональный программист 1С с более чем 10-летним опытом. Разработка, интеграция, оптимизация бизнес-процессов.",
- 'meta_keywords': "программист 1С Николай Сердюк, опыт работы 1С, компетенции 1С, проекты 1С"
- }
- 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,
- 'title': "Проекты"
- }
- 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': "Компетенции"
- }
- 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': "Отзывы"
- }
- 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')
-=======
from django.http import HttpResponse, HttpResponseNotFound
from .models import *
from django.shortcuts import render, redirect
@@ -512,4 +257,3 @@ def statistics_view(request):
@require_GET
def robots_txt(request):
return render(request, 'robots.txt', content_type='text/plain')
->>>>>>> master