Один из принципов оптимизации сайта для поисковых систем - это создание карты сайта Sitemap. Благодаря этой странице поисковые системы узнают какие страницы были обновлены или созданы. В Django уже существуют встроенные механизмы для создания таких карт в формате XML. В рамках этой статьи мы рассмотрим как создать такую карту на основе существующих моделей или и для прямых ссылок с помощью urls.py.
Подготовка тестового проекта
У вас уже должен быть установлен Django. С помощью следующей команды мы создадим проект с названием 'django_project':
django-admin startproject django_project
В это проекте мы создадим приложение:
cd django_project
python manage.py startapp mapapp
Это приложение мы должны добавить в файл 'settings.py' в 'INSTALLED_APPS':
vim django_project/settings.py
'mapapp.apps.MapappConfig'
Что бы наше приложение имело свой собственный файл маршрутов (urls.py) мы должны расширить основной файл добавив в него метод 'include':
vim django_project/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('mapapp.urls')),
]
В папке 'mapapp' создадим файл 'urls.py', который будет содержать маршруты и функции. Их мы создадим позже:
vim mapapp/urls.py
from django.urls import path
from .views import about, news
urlpatterns = [
path('about/', about, name='about-page'),
path('news/<pk>/', news, name='news-page'),
]
Создадим модель с методом get_absolute_url(), который будет возвращать прямую ссылку на каждый из созданных объектов:
vim mapapp/models.py
from django.db import models
class NewsModel(models.Model):
title = models.CharField(max_length=120)
url = models.CharField(max_length=140)
date = models.DateField()
def get_absolute_url(self):
return f'/{self.pk}'
Проведем миграции:
python manage.py makemigrations
python manage.py migrate
Создание вьюшек не обязательно, но у вас могут появиться ошибки так как они импортируются в urls.py. Для примера можно создать следующие:
from django.shortcuts import render, HttpResponse
from .models import News
def about(request):
return HttpResponse('Hello 1')
def news(request):
return HttpResponse(News.objects.get(id=pk).title)
Вы можете добавить данные в базу используя shell или панель администрирования.
Создание прямой ссылки в Django с get_absolute_url
Создание карты сайта
Для создания карты сайта используется приложение 'django.contrib.sitemaps'. Что бы его можно было использовать мы так же должны добавить его в 'INSTALLED_APPS':
vim django_project/settings.py
'django.contrib.sitemaps'
Это приложение не нуждается в дополнительных таблицах в базе данных, поэтому миграции выполнять не нужно
Все классы, через которые мы будем объявлять карты для сайта, принято создавать в каталоге приложения для которого эта карта создается. В этом каталоге создается файл sitemap.py:
vim myapp/sitemap.py
Логически мы можем разделить страницы нашего сайта на 2 типа:
- Статические страницы - например страницы "О компании", всегда хранящееся по ссылке 'about/' или имеющая аналогичное имя. Url этой страницы статичный и не берется из базы;
- Для динамических страниц - например товары или новости. Каждая ссылка новости состоит из какого-то слова и значения из базы. В urls.py обычно они выглядят как 'news/<pk>/'.
Что бы мы могли создавать карту нужно использовать классы унаследованные от Sitemap. В этих классах мы обязаны определить 2 метода:
- items - представляет собой объект для создания ссылки. Не важно какой тип данных тут находится;
- location - генерирует ссылку из части items.
Для статической страницы 'about/' класс sitemap будет выглядеть следующим образом:
from django.contrib.sitemaps import Sitemap
from django.shortcuts import reverse
class StaticViewSitemap(Sitemap):
def items(self):
return ['about-page']
def location(self, item):
return reverse(item)
Если мы хотим создать sitemap из динамических данных, url которых состоит из значений базы данных, то можем использовать следующий способ:
from django.contrib.sitemaps import Sitemap
from .models import News
from django.shortcuts import reverse
class DynamicViewSitemap(Sitemap):
def items(self):
return News.objects.all()
def location(self, item):
# return reverse('news-page', args=[item.pk])
return f'/news/{item.pk}/'
При этом location, в случае работы с моделью, можно не указывать если у вас создан метод get_absolute_url().
urls.py
Что бы вывести результат работы этих классов в виде xml объектов мы должны объединить их в словаре и связать c url:
vim mapapp/urls.py
from django.urls import path
from .views import about, news
from .sitemap import StaticViewSitemap, DynamicViewSitemap
from django.contrib.sitemaps.views import sitemap
sitemaps = {
'static': StaticViewSitemap,
'dynamic': DynamicViewSitemap
}
urlpatterns = [
path('about/', about, name='about-page'),
path('news/<int:pk>/', news, name='news-page'),
path('sitemap.xml', sitemap, {'sitemaps': sitemaps}),
]
Результат мы можем увидеть при запуске сервера:
Поисковые системы работают по-разному. В основном все поисковые системы будут относить карту сайта созданную по пути '/news/sitemap.xml' к самому адресу 'news'. Каждую из карт сайта может проиндексировать сама поисковая система либо она может быть добавлена руками в панели вебмастера. Кроме этого и частоту проверки чтения sitemap, у некоторых поисковых систем, так же можно изменить.
Формат sitemap подразумевает следующие дополнительные данные, которые может прочитать поисковая система:
- lastmod - дата и время изменения страницы (формат datetime);
- changefreq - частота изменения страницы;
- priority - приоритет по которому поисковик будет обходить эту ссылку (значение от 0.0 до 1.0);
- limit - лимит на количество ссылок в одной карте (по умолчанию 5000).
changefreq и priority
Пример использования этих возможностей:
from django.contrib.sitemaps import Sitemap
from django.shortcuts import reverse
class StaticViewSitemap(Sitemap):
changefreq = 'monthly'
priority = 0.9
def items(self):
return ['about-page']
def location(self, item):
return reverse(item)
Changefreq может принимать следующие значения:
- 'always'
- 'hourly'
- 'daily'
- 'weekly'
- 'monthly'
- 'yearly'
- 'never'
lastmod
Для вывода lastmod мы должны объявить функцию возвращающую объект datetime. В модели мы создавали поле такое поле - используем его:
from django.contrib.sitemaps import Sitemap
class DynamicViewSitemap(Sitemap):
changefreq = 'monthly'
priority = 0.9
def items(self):
return News.objects.all()
def location(self, item):
return f'/news/{item.pk}/'
def lastmod(self, item):
return item.date
...