diff --git a/oknardia/oknardia/settings.py b/oknardia/oknardia/settings.py
index cfc45f1..e9f84de 100644
--- a/oknardia/oknardia/settings.py
+++ b/oknardia/oknardia/settings.py
@@ -50,6 +50,7 @@ INSTALLED_APPS = [
'django.contrib.staticfiles',
'django.contrib.humanize',
+ # 'django.contrib.sitemaps',
'oknardia.apps.OknardiaConfig',
'web.apps.WebConfig',
@@ -107,8 +108,8 @@ USE_I18N = True
USE_TZ = True
FIRST_DAY_OF_WEEK = 1 # 1'st day week -- monday
SHORT_DATE_FORMAT = 'Y-m-d'
-SHORT_DATETIME_FORMAT = 'Y-m-d H:M:S'
-DATETIME_FORMAT = 'Y-m-d H:M:S'
+SHORT_DATETIME_FORMAT = 'Y-m-d H:i:s'
+DATETIME_FORMAT = 'Y-m-d H:i:s'
# Статические файлы (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.1/howto/static-files/
@@ -119,6 +120,7 @@ MEDIA_URL = 'media/'
if DEBUG: # DEBUG: заменяем настройки прода, на настройки девопа
MEDIA_ROOT = MY_MEDIA_ROOT_DEV1 if socket.gethostname() == MY_HOST_HOME1 else MY_MEDIA_ROOT_DEV2
+ SITEMAP_ROOT = MY_SITEMAP_ROOT_DEV1 if socket.gethostname() == MY_HOST_HOME1 else MY_SITEMAP_ROOT_DEV2
# STATIC_ROOT = MY_STATIC_ROOT_DEV1 if socket.gethostname() == MY_HOST_HOME1 else MY_STATIC_ROOT_DEV2
STATICFILES_DIRS = [
MY_STATIC_ROOT_DEV1 if socket.gethostname() == MY_HOST_HOME1 else MY_STATIC_ROOT_DEV2,
@@ -141,6 +143,7 @@ else:
MEDIA_ROOT = MY_MEDIA_ROOT_PROD
# STATICFILES_DIRS = [MY_STATIC_ROOT_PROD1, ]
STATIC_ROOT = MY_STATIC_ROOT_PROD
+ SITEMAP_ROOT = MY_SITEMAP_ROOT_PROD
# путь к каталогу static (в эту переменную использовать для указания пути где будут делаться кэш-блоки для шаблонов)
STATIC_BASE_PATH = MY_STATIC_BASE_PATH_PROD
DATABASES = {
diff --git a/oknardia/oknardia/urls.py b/oknardia/oknardia/urls.py
index 49ddd8b..f3f4a97 100644
--- a/oknardia/oknardia/urls.py
+++ b/oknardia/oknardia/urls.py
@@ -95,7 +95,9 @@ urlpatterns = [
# --- страничка для тестирования верстки текста в блоге
re_path(r'^service/tmp[/*]$', service.tmp),
# --- страничка "нет доступа"
- re_path(r'^not-denice[/*]$', service.not_denice),
+ re_path(r'^service/not-denice[/*]$', service.not_denice),
+ # --- создание файлов sitemap.xml
+ re_path(r'^service/make_sitemaps[/*]$', service.make_site_maps),
]
diff --git a/oknardia/templates/service/index.html b/oknardia/templates/service/index.html
index 275bed1..c71dd60 100755
--- a/oknardia/templates/service/index.html
+++ b/oknardia/templates/service/index.html
@@ -10,9 +10,9 @@
Служебные ссылки
diff --git a/oknardia/web/service.py b/oknardia/web/service.py
index 976fcc3..dfa8da5 100644
--- a/oknardia/web/service.py
+++ b/oknardia/web/service.py
@@ -1,7 +1,14 @@
# -*- coding: utf-8 -*-
from django.shortcuts import render, redirect
from django.http import HttpRequest, HttpResponse
+from oknardia.models import PVCprofiles, Seria_Info, Win_MountDim, Building_Info, SetKit
+from datetime import datetime, timezone
+import django.utils.dateformat
+import django.utils.timezone
+from oknardia.settings import *
import time
+import random
+import pytils
# Главная страница для вызова служебных процедур.
@@ -15,7 +22,7 @@ def service(request: HttpRequest) -> HttpResponse:
# проверка на аутентификацию
print(request.user.is_authenticated)
if not request.user.is_authenticated:
- return redirect("service/not-denice")
+ return redirect("/service/not-denice")
return render(request, "service/index.html", {'ticks': float(time.time()-time_start)})
@@ -33,3 +40,185 @@ def tmp(request: HttpRequest) -> HttpResponse:
"""
t_start = time.time()
return render(request, "service/tmp.html", {'TAU': float(time.time()-t_start)})
+
+
+SITEMAP_MAX_ITEM = 40000 # максимальное число URL-ов в sitemap.xml -- 50000
+SITEMAP_MAX_FILE_SIZE = 5242880 # максимальный размер файла sitemap.xml -- 10Mb (10485760 байт)
+SITEMAP_MAX_FILES_QTY = 998 # максимальный число вложенных sitemap.xml -- 1000
+
+
+def str_time() -> str:
+ """ Возвращает текущее время в ISO 8601 со смещением от текущего часового пояса
+ """
+ return django.utils.dateformat.format(django.utils.timezone.now(), 'c')
+
+
+def make_site_maps (request: HttpRequest) -> HttpResponse:
+ """Функция создания sitemap.xml ... периодически надо вызывать через crone
+
+ :param request: request
+ :return: HttpResponse ( msg )
+ """
+ msg = ""
+ time_start = time.time()
+ count_total_item = 0
+ count_item_per_file = 0
+ count_file = 0
+ # форматирование даты-времени в ISO 8601 со смещением от текущего часового пояса
+ # str_time = django.utils.dateformat.format(django.utils.timezone.now(), 'c') # форматирование даты в ISO 8601
+ # ПОЛУЧАЕМ ВСЕ СТРАНИЧКИ С ЦЕНАМИ ДЛЯ ОДИНОЧНОГО ПРОЕМА
+ q1 = Win_MountDim.objects.raw("SELECT"
+ " oknardia_win_mountdim.iWinWidth,"
+ " oknardia_win_mountdim.iWinHight,"
+ " oknardia_win_mountdim.id,"
+ " COUNT(oknardia_priceoffer.kOffer2MountDim_id) AS NumOffer,"
+ " oknardia_win_mountdim.sFlapConfig "
+ "FROM oknardia_priceoffer"
+ " INNER JOIN oknardia_win_mountdim"
+ " ON oknardia_priceoffer.kOffer2MountDim_id = oknardia_win_mountdim.id "
+ "GROUP BY oknardia_win_mountdim.id,"
+ " oknardia_win_mountdim.iWinWidth,"
+ " oknardia_win_mountdim.iWinHight,"
+ " oknardia_win_mountdim.sFlapConfig "
+ "ORDER BY COUNT(oknardia_priceoffer.kOffer2MountDim_id);")
+ for i in q1:
+ msg += f" \n" \
+ f" https://oknardia.ru/tsena-odnogo-okna/{int(i.iWinWidth*10)}x{int(i.iWinHight*10)}mm/tip{i.id}\n"\
+ f" {str_time()}\n weekly\n 0.5\n" \
+ f" \n"
+ count_total_item += 1
+ # print "~~~> ", countTotalItem, " ::: /compare_offers/", Count
+ count_item_per_file += 1
+ if (count_item_per_file > SITEMAP_MAX_ITEM) or (len(msg) > SITEMAP_MAX_FILE_SIZE):
+ # Файл sitemap.xml заполнен... нужно записать и продолжить записывать в следующем
+ msg = f"" \
+ f"\n{msg}"
+ with open(f"{SITEMAP_ROOT}sitemap{count_file:04d}.xml", "w", encoding="utf-8") as f:
+ f.write(msg)
+ count_item_per_file = 0
+ count_file += 1 # счетчик файлов
+ if count_file > SITEMAP_MAX_FILES_QTY: # максимально число файлов SITEMAP_MAX_FILES_QTY
+ break
+ msg = "" # обнулить буфер для записи файла
+ # ВСЕ СТРАНИЧКИ С ЦЕНОВЫМИ ПРЕДЛОЖЕНИЯМИ ПО АДРЕСАМ
+ q1 = Building_Info.objects.raw(
+ "SELECT DISTINCT oknardia_building_info.sAddress, oknardia_building_info.id as id,"
+ " oknardia_apartment_type.id AS ap_id "
+ "FROM oknardia_building_info"
+ " INNER JOIN oknardia_seria_info"
+ " ON oknardia_building_info.kSeria_Link_id = oknardia_seria_info.id"
+ " INNER JOIN oknardia_apartment_type"
+ " ON oknardia_apartment_type.kSeria_id = oknardia_seria_info.kRoot_id "
+ "ORDER BY oknardia_building_info.id;")
+ list_build = list(q1)
+ random.shuffle(list_build) # перемешиваем случайным образом, чтобы поисковики видели изменения sitemap
+ for i in list_build:
+ msg += f" \n https://oknardia.ru/{i.id}/{i.ap_id}/{pytils.translit.slugify(i.sAddress)}\n" \
+ f" {str_time()}\n weekly\n 0.5\n" \
+ f" \n"
+ count_total_item += 1
+ # print("===> ", count_total_item, " ::: ", i.id, '/', i.ap_id, '/', pytils.translit.slugify(i.sAddress), sep="")
+ count_item_per_file += 1
+ if (count_item_per_file > SITEMAP_MAX_ITEM) or (len(msg) > SITEMAP_MAX_FILE_SIZE):
+ # Файл sitemap.xml заполнен... нужно записать и продолжить записывать в следующем
+ msg = f"\n" \
+ f"\n{msg}"
+ with open(f"{SITEMAP_ROOT}sitemap{count_file:04d}.xml", "w", encoding="utf-8") as f:
+ f.write(msg)
+ count_item_per_file = 0
+ count_file += 1 # счетчик файлов
+ if count_file > SITEMAP_MAX_FILES_QTY: # максимально число файлов SITEMAP_MAX_FILES_QTY
+ break
+ msg = "" # обнулить буфер для записи файла
+
+ # ДОБАВЛЯЕМ В SITEMAP ВСЕ СТРАНИЧКИ СО СРВНЕНИЕМ НАБОРОВ
+ dim_comp = compare()
+ random.shuffle(dim_comp)
+ for i in dim_comp:
+ msg += f" \n https://oknardia.ru/compare_offers/{i}\n {str_time()}\n" \
+ f" weekly\n 0.45\n \n"
+ count_total_item += 1
+ count_item_per_file += 1
+ if (count_item_per_file > SITEMAP_MAX_ITEM) or (len(msg) > SITEMAP_MAX_FILE_SIZE):
+ # Файл sitemap.xml заполнен... нужно записать и продолжить записывать в следующем
+ msg = f"\n" \
+ f"\n{msg}"
+ with open(f"{SITEMAP_ROOT}sitemap{count_file:04d}.xml", "w", encoding="utf-8") as f:
+ f.write(msg)
+ count_item_per_file = 0
+ count_file += 1 # счетчик файлов
+ msg = "" # обнулить буфер для записи файла
+ if count_file > SITEMAP_MAX_FILES_QTY: # максимально число файлов SITEMAP_MAX_FILES_QTY
+ break
+
+ # ЗАВЕРШАЕМ
+ if count_file == 0:
+ # Все ссылки уместились в один sitemap.xml... просто его записать
+ with open(f"{SITEMAP_ROOT}sitemap.xml", "w", encoding="utf-8") as f:
+ f.write(f"\n"
+ f"\n{msg}")
+ print(SITEMAP_ROOT)
+ msg = f"Создан единственный sitemap.xml\nВсего ссылок: {count_total_item:06d}"
+ else:
+ # Файлов sitemap.xml много.
+ # Создаем завершающий файл sitemap
+ with open(f"{SITEMAP_ROOT}sitemap{count_file:04d}.xml", "w", encoding="utf-8") as f:
+ f.write(f"\n\n{msg}")
+ # Создаём объединяющий sitemap.xml с перечислением всего множества sitemap-файлов...
+ msg = "\n" \
+ "\n"
+ for i in range(0, count_file+1):
+ msg += f" \n https://oknardia.ru/sitemap{i:04d}.xml\n" \
+ f" {str_time()}\n \n"
+ msg += u""
+ with open(f"{SITEMAP_ROOT}sitemap.xml", "w", encoding="utf-8") as f:
+ f.write(msg)
+ msg = f"Создан каскадный sitemap.xml\nВсего вложенных файлов: {count_file+1:04d}\n" \
+ f"Всего ссылок: {count_total_item:08d}"
+ print(msg)
+ return HttpResponse(f"
{msg}\n\nвремя выполнения: {float(time.time()-time_start)} сек.")
+
+
+def compare() -> list:
+ """ Возвращает список сравнения из всех возможных вариантов сравнения оконных наборов (из доступных в базе)
+
+ :return: список сравнения
+ """
+ q_set_kit = SetKit.objects.raw('SELECT oknardia_setkit.id, oknardia_setkit.sSetActive '
+ 'FROM oknardia_setkit '
+ 'WHERE oknardia_setkit.sSetActive = TRUE')
+ count = 0
+ dim_comp = []
+ l_set_kit = list(q_set_kit)
+ for i1 in l_set_kit:
+ for i2 in l_set_kit:
+ if i1.id >= i2.id:
+ continue
+ dim_comp.append(f"{i1.id},{i2.id}")
+ count += 1
+ for i3 in l_set_kit:
+ if i2.id >= i3.id:
+ continue
+ dim_comp.append(f"{i1.id},{i2.id},{i3.id}")
+ count += 1
+ for i4 in l_set_kit:
+ if i3.id >= i4.id:
+ continue
+ dim_comp.append(f"{i1.id},{i2.id},{i3.id},{i4.id}")
+ count += 1
+ for i5 in l_set_kit:
+ if i4.id >= i5.id:
+ continue
+ dim_comp.append(f"{i1.id},{i2.id},{i3.id},{i4.id},{i5.id}")
+ count += 1
+ for i6 in l_set_kit:
+ if i5.id >= i6.id:
+ continue
+ dim_comp.append(f"{i1.id},{i2.id},{i3.id},{i4.id},{i5.id},{i6.id}")
+ count += 1
+ # random.shuffle(dim_comp)
+ # for i1 in dim_comp:
+ # print(i1)
+ # print(f"---------------{count}---------------")
+ return dim_comp