diff --git a/OneCprogsite/OneCprogsite/__pycache__/settings.cpython-310.pyc b/OneCprogsite/OneCprogsite/__pycache__/settings.cpython-310.pyc index 1089903..b93c66d 100644 Binary files a/OneCprogsite/OneCprogsite/__pycache__/settings.cpython-310.pyc and b/OneCprogsite/OneCprogsite/__pycache__/settings.cpython-310.pyc differ diff --git a/OneCprogsite/OneCprogsite/settings.py b/OneCprogsite/OneCprogsite/settings.py index b2bd6d9..65ac19e 100644 --- a/OneCprogsite/OneCprogsite/settings.py +++ b/OneCprogsite/OneCprogsite/settings.py @@ -40,6 +40,8 @@ INSTALLED_APPS = [ 'programmer.apps.ProgrammerConfig', 'django_bootstrap5', 'django_extensions', + 'django.contrib.sites', + 'django.contrib.sitemaps', ] MIDDLEWARE = [ diff --git a/OneCprogsite/programmer/__pycache__/models.cpython-310.pyc b/OneCprogsite/programmer/__pycache__/models.cpython-310.pyc index cbbb6fa..f6d816b 100644 Binary files a/OneCprogsite/programmer/__pycache__/models.cpython-310.pyc and b/OneCprogsite/programmer/__pycache__/models.cpython-310.pyc differ diff --git a/OneCprogsite/programmer/__pycache__/sitemaps.cpython-310.pyc b/OneCprogsite/programmer/__pycache__/sitemaps.cpython-310.pyc new file mode 100644 index 0000000..46831ac Binary files /dev/null and b/OneCprogsite/programmer/__pycache__/sitemaps.cpython-310.pyc differ diff --git a/OneCprogsite/programmer/__pycache__/urls.cpython-310.pyc b/OneCprogsite/programmer/__pycache__/urls.cpython-310.pyc index a20925c..b007e84 100644 Binary files a/OneCprogsite/programmer/__pycache__/urls.cpython-310.pyc and b/OneCprogsite/programmer/__pycache__/urls.cpython-310.pyc differ diff --git a/OneCprogsite/programmer/__pycache__/views.cpython-310.pyc b/OneCprogsite/programmer/__pycache__/views.cpython-310.pyc index 40fbb99..8ad2d2d 100644 Binary files a/OneCprogsite/programmer/__pycache__/views.cpython-310.pyc and b/OneCprogsite/programmer/__pycache__/views.cpython-310.pyc differ diff --git a/OneCprogsite/programmer/management/__init__.py b/OneCprogsite/programmer/management/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/OneCprogsite/programmer/management/__pycache__/__init__.cpython-310.pyc b/OneCprogsite/programmer/management/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000..fb39175 Binary files /dev/null and b/OneCprogsite/programmer/management/__pycache__/__init__.cpython-310.pyc differ diff --git a/OneCprogsite/programmer/management/commands/__init__.py b/OneCprogsite/programmer/management/commands/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/OneCprogsite/programmer/management/commands/__pycache__/__init__.cpython-310.pyc b/OneCprogsite/programmer/management/commands/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000..5b2a135 Binary files /dev/null and b/OneCprogsite/programmer/management/commands/__pycache__/__init__.cpython-310.pyc differ diff --git a/OneCprogsite/programmer/management/commands/__pycache__/test_sitemap.cpython-310.pyc b/OneCprogsite/programmer/management/commands/__pycache__/test_sitemap.cpython-310.pyc new file mode 100644 index 0000000..f541224 Binary files /dev/null and b/OneCprogsite/programmer/management/commands/__pycache__/test_sitemap.cpython-310.pyc differ diff --git a/OneCprogsite/programmer/management/commands/test_sitemap.py b/OneCprogsite/programmer/management/commands/test_sitemap.py new file mode 100644 index 0000000..338d65d --- /dev/null +++ b/OneCprogsite/programmer/management/commands/test_sitemap.py @@ -0,0 +1,27 @@ +from django.core.management.base import BaseCommand +from django.contrib.sitemaps import Sitemap +from django.urls import reverse +from programmer.models import Home, Solution, Competence, Recall + + +class Command(BaseCommand): + help = 'Test sitemap generation' + + def handle(self, *args, **options): + from programmer.sitemaps import sitemaps + + self.stdout.write('Testing sitemap generation...') + + for name, sitemap in sitemaps.items(): + self.stdout.write(f'\n{name}:') + items = sitemap().items() + self.stdout.write(f' Items found: {len(items)}') + + for item in items[:3]: # Показываем первые 3 элемента + try: + url = sitemap().location(item) + self.stdout.write(f' - {url}') + except Exception as e: + self.stdout.write(f' - Error: {e}') + + self.stdout.write('\nSitemap test completed!') diff --git a/OneCprogsite/programmer/models.py b/OneCprogsite/programmer/models.py index 5cd7369..065b6aa 100644 --- a/OneCprogsite/programmer/models.py +++ b/OneCprogsite/programmer/models.py @@ -1,6 +1,9 @@ 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 class Recall(models.Model): @@ -125,3 +128,12 @@ class Visitor(models.Model): 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') diff --git a/OneCprogsite/programmer/sitemaps.py b/OneCprogsite/programmer/sitemaps.py new file mode 100644 index 0000000..e71f587 --- /dev/null +++ b/OneCprogsite/programmer/sitemaps.py @@ -0,0 +1,64 @@ +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, +} \ No newline at end of file diff --git a/OneCprogsite/programmer/templates/programmer/about.html b/OneCprogsite/programmer/templates/programmer/about.html index dde749e..696fa6d 100644 --- a/OneCprogsite/programmer/templates/programmer/about.html +++ b/OneCprogsite/programmer/templates/programmer/about.html @@ -118,4 +118,37 @@ + + {% endblock %} \ No newline at end of file diff --git a/OneCprogsite/programmer/templates/programmer/base.html b/OneCprogsite/programmer/templates/programmer/base.html index 09665ea..6477bc2 100644 --- a/OneCprogsite/programmer/templates/programmer/base.html +++ b/OneCprogsite/programmer/templates/programmer/base.html @@ -5,6 +5,28 @@ {{title}} - Программист 1С + + + + + + + + + + + + + + + + + + + + + + {% bootstrap_css %} @@ -339,6 +361,58 @@ {% block extra_css %} {% endblock %} + + + + + + + + + + + diff --git a/OneCprogsite/programmer/templates/programmer/humans.txt b/OneCprogsite/programmer/templates/programmer/humans.txt new file mode 100644 index 0000000..7a8f4bc --- /dev/null +++ b/OneCprogsite/programmer/templates/programmer/humans.txt @@ -0,0 +1,13 @@ +/* TEAM */ +Developer: Николай Сердюк +Site: https://nikdizell.ru +Email: {{ CONTACT_EMAIL }} + +/* THANKS */ +Django Framework +Bootstrap + +/* SITE */ +Last update: 2025 +Language: Russian +Doctype: HTML5 \ No newline at end of file diff --git a/OneCprogsite/programmer/templates/programmer/robots.txt b/OneCprogsite/programmer/templates/programmer/robots.txt new file mode 100644 index 0000000..4351856 --- /dev/null +++ b/OneCprogsite/programmer/templates/programmer/robots.txt @@ -0,0 +1,18 @@ +User-agent: * +Allow: / + +# Основной сайт +Sitemap: {{ request.scheme }}://{{ request.get_host }}/sitemap.xml + +# Запрещаем служебные разделы +Disallow: /admin/ +Disallow: /static/admin/ +Disallow: /callback/ +Disallow: /api/ + +# Разрешаем индексацию статических файлов +Allow: /static/ +Allow: /media/ + +# Указываем главное зеркало +Host: {{ request.scheme }}://{{ request.get_host }} \ No newline at end of file diff --git a/OneCprogsite/programmer/templates/programmer/sitemap.xml b/OneCprogsite/programmer/templates/programmer/sitemap.xml new file mode 100644 index 0000000..62e1b06 --- /dev/null +++ b/OneCprogsite/programmer/templates/programmer/sitemap.xml @@ -0,0 +1,12 @@ + + +{% 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 %} + \ No newline at end of file diff --git a/OneCprogsite/programmer/urls.py b/OneCprogsite/programmer/urls.py index 51e8c5a..ed69c18 100644 --- a/OneCprogsite/programmer/urls.py +++ b/OneCprogsite/programmer/urls.py @@ -3,6 +3,9 @@ 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'), @@ -13,7 +16,12 @@ urlpatterns = [ 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: urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) \ No newline at end of file diff --git a/OneCprogsite/programmer/views.py b/OneCprogsite/programmer/views.py index 92ad499..c41256e 100644 --- a/OneCprogsite/programmer/views.py +++ b/OneCprogsite/programmer/views.py @@ -9,6 +9,7 @@ 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 = [ @@ -107,6 +108,8 @@ def index(request): '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) @@ -116,7 +119,9 @@ def index(request): def about(request): context = { 'menu': menu, - 'title': "Обо мне" + 'title': "Обо мне - Программист 1С", + 'meta_description': "Николай Сердюк - профессиональный программист 1С с более чем 10-летним опытом. Разработка, интеграция, оптимизация бизнес-процессов.", + 'meta_keywords': "программист 1С Николай Сердюк, опыт работы 1С, компетенции 1С, проекты 1С" } return render(request, 'programmer/about.html', context=context) @@ -233,3 +238,8 @@ def statistics_view(request): } return render(request, 'admin/statistics.html', context) + + +@require_GET +def robots_txt(request): + return render(request, 'robots.txt', content_type='text/plain')