Оптимизация под поисковую выдачу
This commit is contained in:
parent
32b1ec4379
commit
cfd318955b
Binary file not shown.
@ -40,6 +40,8 @@ INSTALLED_APPS = [
|
||||
'programmer.apps.ProgrammerConfig',
|
||||
'django_bootstrap5',
|
||||
'django_extensions',
|
||||
'django.contrib.sites',
|
||||
'django.contrib.sitemaps',
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
|
||||
Binary file not shown.
BIN
OneCprogsite/programmer/__pycache__/sitemaps.cpython-310.pyc
Normal file
BIN
OneCprogsite/programmer/__pycache__/sitemaps.cpython-310.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
0
OneCprogsite/programmer/management/__init__.py
Normal file
0
OneCprogsite/programmer/management/__init__.py
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
27
OneCprogsite/programmer/management/commands/test_sitemap.py
Normal file
27
OneCprogsite/programmer/management/commands/test_sitemap.py
Normal file
@ -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!')
|
||||
@ -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')
|
||||
|
||||
64
OneCprogsite/programmer/sitemaps.py
Normal file
64
OneCprogsite/programmer/sitemaps.py
Normal file
@ -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,
|
||||
}
|
||||
@ -118,4 +118,37 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "Service",
|
||||
"serviceType": "1С программирование",
|
||||
"provider": {
|
||||
"@type": "Person",
|
||||
"name": "Николай Сердюк"
|
||||
},
|
||||
"areaServed": "Россия",
|
||||
"hasOfferCatalog": {
|
||||
"@type": "OfferCatalog",
|
||||
"name": "Услуги программиста 1С",
|
||||
"itemListElement": [
|
||||
{
|
||||
"@type": "Offer",
|
||||
"itemOffered": {
|
||||
"@type": "Service",
|
||||
"name": "Разработка конфигураций 1С"
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "Offer",
|
||||
"itemOffered": {
|
||||
"@type": "Service",
|
||||
"name": "Интеграция 1С с веб-сервисами"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
||||
@ -5,6 +5,28 @@
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<title>{{title}} - Программист 1С</title>
|
||||
<!-- Основные мета-теги -->
|
||||
<meta name="description" content="{% block meta_description %}Профессиональный программист 1С с более чем 10-летним опытом. Разработка, интеграция и оптимизация систем 1С.{% endblock %}">
|
||||
<meta name="keywords" content="{% block meta_keywords %}программист 1С, разработка 1С, интеграция 1С, оптимизация 1С, 1С предприятие{% endblock %}">
|
||||
<meta name="author" content="Николай Сердюк">
|
||||
|
||||
<!-- Open Graph для соцсетей -->
|
||||
<meta property="og:title" content="{{title}} - Программист 1С">
|
||||
<meta property="og:description" content="Профессиональный программист 1С с более чем 10-летним опытом">
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:url" content="{{ request.build_absolute_uri }}">
|
||||
<meta property="og:image" content="{% static 'programmer/images/og-image.jpg' %}">
|
||||
<meta property="og:site_name" content="Программист 1С - Николай Сердюк">
|
||||
|
||||
<!-- Twitter Card -->
|
||||
<meta name="twitter:card" content="summary_large_image">
|
||||
<meta name="twitter:title" content="{{title}} - Программист 1С">
|
||||
<meta name="twitter:description" content="Профессиональный программист 1С с более чем 10-летним опытом">
|
||||
<meta name="twitter:image" content="{% static 'programmer/images/og-image.jpg' %}">
|
||||
|
||||
<!-- Дополнительные SEO-теги -->
|
||||
<meta name="robots" content="index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1">
|
||||
<link rel="canonical" href="{{ request.build_absolute_uri }}">
|
||||
{% bootstrap_css %}
|
||||
|
||||
<!-- Основной CSS файл (темная тема по умолчанию) -->
|
||||
@ -339,6 +361,58 @@
|
||||
{% block extra_css %}
|
||||
<!-- Дополнительные CSS файлы для конкретных страниц -->
|
||||
{% endblock %}
|
||||
|
||||
<!-- Google Analytics -->
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=G-X3W9YSQHRM"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'G-X3W9YSQHRM');
|
||||
</script>
|
||||
|
||||
<!-- Яндекс.Метрика -->
|
||||
<script type="text/javascript">
|
||||
(function(m,e,t,r,i,k,a){
|
||||
m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
|
||||
m[i].l=1*new Date();
|
||||
for (var j = 0; j < document.scripts.length; j++) {if (document.scripts[j].src === r) { return; }}
|
||||
k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)
|
||||
})(window, document,'script','https://mc.yandex.ru/metrika/tag.js?id=105278924', 'ym');
|
||||
|
||||
ym(105278924, 'init', {ssr:true, webvisor:true, clickmap:true, ecommerce:"dataLayer", accurateTrackBounce:true, trackLinks:true});
|
||||
</script>
|
||||
<noscript><div><img src="https://mc.yandex.ru/watch/105278924" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
|
||||
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "Person",
|
||||
"name": "Николай Сердюк",
|
||||
"jobTitle": "Программист 1С",
|
||||
"description": "Профессиональный программист 1С с более чем 10-летним опытом",
|
||||
"url": "https://nikdizell.ru",
|
||||
"email": "{{ CONTACT_EMAIL }}",
|
||||
"telephone": "{{ CONTACT_PHONE }}",
|
||||
"knowsAbout": [
|
||||
"1С:Предприятие 8.3",
|
||||
"Управление торговлей",
|
||||
"Бухгалтерия предприятия",
|
||||
"Зарплата и управление персоналом",
|
||||
"SQL",
|
||||
"Веб-сервисы",
|
||||
"API интеграция"
|
||||
],
|
||||
"hasOccupation": {
|
||||
"@type": "Occupation",
|
||||
"name": "Программист 1С",
|
||||
"description": "Разработка и сопровождение систем на платформе 1С",
|
||||
"occupationLocation": "Россия"
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<!-- Header -->
|
||||
|
||||
13
OneCprogsite/programmer/templates/programmer/humans.txt
Normal file
13
OneCprogsite/programmer/templates/programmer/humans.txt
Normal file
@ -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
|
||||
18
OneCprogsite/programmer/templates/programmer/robots.txt
Normal file
18
OneCprogsite/programmer/templates/programmer/robots.txt
Normal file
@ -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 }}
|
||||
12
OneCprogsite/programmer/templates/programmer/sitemap.xml
Normal file
12
OneCprogsite/programmer/templates/programmer/sitemap.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
|
||||
xmlns:xhtml="http://www.w3.org/1999/xhtml">
|
||||
{% for url in urlset %}
|
||||
<url>
|
||||
<loc>{{ url.location }}</loc>
|
||||
{% if url.lastmod %}<lastmod>{{ url.lastmod|date:"Y-m-d" }}</lastmod>{% endif %}
|
||||
{% if url.changefreq %}<changefreq>{{ url.changefreq }}</changefreq>{% endif %}
|
||||
{% if url.priority %}<priority>{{ url.priority }}</priority>{% endif %}
|
||||
</url>
|
||||
{% endfor %}
|
||||
</urlset>
|
||||
@ -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/<int:post_id>/', 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)
|
||||
@ -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')
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user