5 Commits

Author SHA1 Message Date
e15017f3a6 add: Страницы обработки ошибок
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 42s
2026-05-21 00:42:54 +03:00
958f11f398 mod: Clean-param 2026-05-20 19:54:42 +03:00
3ab38b4885 mod: алиас sitemap sitemap.xml 2026-05-20 19:25:10 +03:00
4b038302c3 add: Добавлен алиас /sitemap.xml -> /media/_serv_sitemap/sitemap.xml в nginx конфиг
- Поисковики ищут sitemap.xml в корне сайта
- Nginx теперь проксирует /sitemap.xml на /media/_serv_sitemap/sitemap.xml
- Установлен кеш на 1 день (чаще обновляется, чем картинки)
2026-05-20 18:38:02 +03:00
3c10b490b3 minor: Улучшены комментарии nginx конфига и исправлен sed паттерн для корректной замены путей
- Уточнены комментарии про архитектуру (медиа, ошибки, sitemap через Django)
- Исправлен sed паттерн: было '/home/user/app/oknardia-site' -> '/home/user/path-to-oknardia-app'
- Улучшен www редирект для правильной подстановки домена
- Убраны дублирующиеся комментарии про требуемую замену
2026-05-20 18:35:07 +03:00
16 changed files with 442 additions and 35 deletions

View File

@@ -1,27 +1,20 @@
# config/nginx/oknardia-app--external-nginx.conf
# ==============================================================================
# ЭТАЛОННЫЙ КОНФИГУРАЦИОННЫЙ ФАЙЛ NGINX (Reverse Proxy для Docker)
# КОНФИГУРАЦИОННЫЙ ФАЙЛ NGINX (Reverse Proxy для Docker + Production)
# ==============================================================================
#
# ВНИМАНИЕ:
# Этот файл является шаблоном. При первом деплое он копируется
# в `/home/user/path-to-oknardia-app/config/nginx/oknardia-app--external-nginx.conf`,
# а затем (уже на хосте, руками) через силинк в `/etc/nginx/sites-available/` и активируется.
# При последующих деплоях `oknardia-app--external-nginx.conf` НЕ ПЕРЕЗАПИСЫВАЕТСЯ,
# чтобы не затереть SSL-сертификаты и ручные правки.
# ИНФОРМАЦИЯ:
# 1. Этот файл используется как шаблон при деплое
# 2. При первом деплое пути `/home/user/path-to-oknardia-app` заменяются на реальный путь через sed
# 3. Сгенерированный конфиг скопируется в `/etc/nginx/sites-available/oknardia`
# 4. Последующие деплои ОБНОВЛЯЮТ этот файл автоматически (sed + копирование)
#
# Если вы изменили этот файл в репозитории и хотите применить изменения на проде:
# вам нужно обновить файл в `/home/user/path-to-oknardia-app/config/nginx/oknardia-app--external-nginx.conf` вручную (diff + copy).
#
# Так же (рядом) будет создан образец этого файла `nginx_oknardia.conf.example`, который будет обновляться при деплоях
# из репозитория, чтобы вы могли видеть, что изменилось и при необходимости перенести эти изменения на прод.
#
# Предполагаемая структура на сервере:
# /home/user/path-to-oknardia-app/
# ├── docker-compose.yml
# ├── .env
# ├── media/ <-- Сюда Nginx смотрит напрямую (Docker volume)
# └── ...
# АРХИТЕКТУРА:
# - Nginx (порты 80/443) <-> Gunicorn контейнер (localhost:8000)
# - Медиа файлы отдаются из `/home/user/path-to-oknardia-app/media/` напрямую
# - Ошибки 5xx берутся из `media/_error` (копируются контейнером при старте)
# - Sitemap.xml отдается через Django/WhiteNoise (в media/_serv_sitemap/)
# - Static файлы (/static/) тоже отдаются через Django/WhiteNoise
# 1. Описываем, где живет наш Django в Docker
upstream oknardia-django {
@@ -70,22 +63,28 @@ server {
# --- МЕДИА ФАЙЛЫ (Загруженный контент) ---
# Nginx отдает их напрямую с диска хоста, не дергая Docker.
# Сюда входит: загруженные картинки, документы, свитмапы, ошибки 5xx
# Путь должен совпадать с тем, где лежит volume на хост-машине.
# ВАЖНО: Убедитесь, что пользователь nginx (www-data) имеет права на чтение этой папки!
# ТРЕБУЕТСЯ ЗАМЕНА ПРИ ДЕПЛОЕ: /home/user/path-to-oknardia-app -> ваш реальный путь
location /media/ {
alias /home/user/path-to-oknardia-app/media/;
expires 30d; # Кешируем картинки на месяц
add_header Cache-Control "public, no-transform";
}
# --- SITEMAP.XML ---
# Sitemap хранится в media/_serv_sitemap/ но должен быть доступен из корня
# для поисковиков (они ищут http://example.com/sitemap.xml)
location = /sitemap.xml {
alias /home/user/path-to-oknardia-app/media/_serv_sitemap/sitemap.xml;
expires 7d; # Кешируем на неделю (редко меняется)
add_header Cache-Control "public";
}
# --- СТРАНИЦЫ ОШИБОК (Custom Error Pages) ---
# Если Django упал (502) или сработал тайм-аут (504), Nginx должен отдать статический HTML.
# Эти файлы должны лежать в папке, доступной Nginx (например, в `media/_error`).
# Эти файлы копируются в `media/_error` при старте контейнера Docker.
#
# ВАЖНО:
# 1. Файлы 50x.html (500, 502, 503, 504) копируются в `media/_error` при старте контейнера (см. docker-compose.prod.yml -> command).
# 2. error_page директива перехватывает ошибки от апстрима (Gunicorn).
# ВАЖНО: error_page директива перехватывает ошибки от апстрима (Gunicorn).
error_page 500 /500.html;
error_page 502 /502.html;
error_page 503 /503.html;
@@ -96,8 +95,6 @@ server {
location = /503.html { root /home/user/path-to-oknardia-app/media/_error; internal; }
location = /504.html { root /home/user/path-to-oknardia-app/media/_error; internal; }
# 404 (и другие) тоже нужно кастомизировать... обычно Django сам отдает 404.
# Но, например, Nginx отдаст 404 при ошике доступа к media-файлам (они храняться на хосте, а не в контейнере)
error_page 400 /400.html;
error_page 401 /401.html;
error_page 403 /403.html;
@@ -112,7 +109,6 @@ server {
location = /413.html { root /home/user/path-to-oknardia-app/media/_error; internal; }
location = /429.html { root /home/user/path-to-oknardia-app/media/_error; internal; }
# Указываем единую страницу (на реконструкции) для всех прочих ошибок
error_page 405 406 407 408 409 410 411 412 414 415 416 417 418 421 422 423 424 425 426 428 431 451 /under_reconstruction.html;
location = /under_reconstruction.html { root /home/user/path-to-oknardia-app/media/_error; internal; }
@@ -141,10 +137,11 @@ server {
}
}
# 3. Редирект с www на без-www (SEO best practice)
# 3. Редирект с www на основной домен (SEO best practice)
server {
server_name www.tmp.oknardia.ru;
listen 80;
return 301 $scheme://oknardia.ru$request_uri; # Всегда редиректим на основной домен
listen [::]:80;
return 301 $scheme://tmp.oknardia.ru$request_uri;
}

View File

@@ -40,11 +40,17 @@ services:
python manage.py regenerate_seria_prerender &&
python manage.py make_rating &&
mkdir -p /nginx_configs_host/nginx &&
sed \"s|/home/user/app/oknardia-site|$${HOST_PROJECT_PATH}|g\" /home/app/config/nginx/oknardia-app--external-nginx.conf > /nginx_configs_host/nginx/oknardia-app--external-nginx.conf.example &&
sed \"s|/home/user/path-to-oknardia-app|$${HOST_PROJECT_PATH}|g\" /home/app/config/nginx/oknardia-app--external-nginx.conf > /nginx_configs_host/nginx/oknardia-app--external-nginx.conf.example &&
if [ ! -f /nginx_configs_host/nginx/oknardia-app--external-nginx.conf ]; then
cp /nginx_configs_host/nginx/oknardia-app--external-nginx.conf.example /nginx_configs_host/nginx/oknardia-app--external-nginx.conf;
echo 'INIT: Created new nginx config with correct paths';
fi &&
ERROR_DIR=/home/app/web/public/media/_error &&
mkdir -p "$$ERROR_DIR" &&
for code in 400 401 403 404 413 429 500 502 503 504; do
cp /home/user/path-to-oknardia-app/oknardia/templates/error/$${code}.html "$$ERROR_DIR/$${code}.html";
done &&
cp /home/user/path-to-oknardia-app/oknardia/templates/error/under_reconstruction.html "$$ERROR_DIR/under_reconstruction.html"
python -m gunicorn --workers 2 --bind 0.0.0.0:8000 --timeout 120 oknardia.wsgi:application"
# Пробрасывание портов

View File

@@ -1,12 +1,12 @@
# -*- coding: utf-8 -*-
"""oknardia Конфигурация URL"""
from django.contrib import admin
from django.urls import include, path, re_path
from django.conf.urls.static import static
from django.urls import include, re_path, path
from django.http import FileResponse
from pathlib import Path
import environ
import mimetypes
import os
# Инициализируем env
env = environ.Env()
@@ -174,10 +174,13 @@ PUBLIC_ROOT_URLPATTERNS = [
# (чтобы отдавать файлы быстро и не проверять остальные рулы)
urlpatterns = [*PUBLIC_ROOT_URLPATTERNS, *urlpatterns]
handler404 = 'web.views.handler404'
handler400 = 'web.views.handler400'
handler403 = 'web.views.handler403'
handler500 = 'web.views.handler500'
# Для локального тестирования production конфига: отдача медиа через Django
# В реальном production медиа обслуживает Nginx!
import os
if DEBUG or env.bool('ALLOW_MEDIA_SERVE', default=False):
from django.views.static import serve as serve_static
# Проверяем что директория медиа существует
@@ -196,6 +199,13 @@ if DEBUG or env.bool('ALLOW_MEDIA_SERVE', default=False):
if DEBUG:
# --- страничка для тестирования верстки текста в блоге
urlpatterns += [re_path(r'^blog/tmp[/*]$', service.tmp),]
# --- странички для тестирования страниц с кодами ошибок
urlpatterns += [
re_path(r'^400$', views.handler400),
re_path(r'^403$', views.handler403),
re_path(r'^404$', views.handler404),
re_path(r'^500$', views.handler500),
]
# ___ ____ _ _____ _ _ _____ _
# | | | | \ ___| |_ _ _ ___ |_ _|___ ___| | |_ ___ ___ | _ |___ ___ ___| |
# |_ | | | | -_| . | | | . | | | | . | . | | . | .'| _| | __| .'| | -_| |

View File

@@ -0,0 +1,31 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>400 — Некорректный запрос</title>
<!-- Аналитика: Google Analytics 4, Yandex.Metrika, Top.Mail.Ru -->
<script src="/static/js/analytics.js" type="text/javascript"></script>
<style>
.container::before {
content: "";
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
background-image: url('/media/img_seria/1LG-504D12_2.jpg');
opacity: 0.6; /* Полупрозрачность только для картинки */
z-index: -1; /* Уводит картинку под текст */
background-position: 18% 15%;
background-repeat: no-repeat;
background-size: 200px auto;
}
</style>
</head>
<body>
<div class="container" style="margin: 10% 0 0 20%;">
<h1 style="font-size: 120px; margin: 0; color: #ccc; background-image: url('/static/img/oknardia_logo.gif'); background-position: left 65%; background-repeat: no-repeat; background-size: 400px auto;"><i style="padding-left: 420px">400</i></h1>
<h2 style="color: #333; font-size: 40px;">Некорректный запрос</h2>
<h4 style="color: #666; margin: 0 0 0 30px; font-size: 20px;">Сервер не может обработать ваш запрос. Пожалуйста, проверьте корректность данных.</h4>
<p style="margin-top: 55px;"><a href="/">Вернуться на главную oknardia.ru</a></p>
</div>
</body>
</html>

View File

@@ -0,0 +1,29 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>401 — Требуется авторизация</title>
<style>
.container::before {
content: "";
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
background-image: url('/media/img_seria/1LG-504D12_2.jpg');
opacity: 0.6;
z-index: -1;
background-position: 18% 15%;
background-repeat: no-repeat;
background-size: 200px auto;
}
</style>
</head>
<body>
<div class="container" style="margin: 10% 0 0 20%;">
<h1 style="font-size: 120px; margin: 0; color: #ccc; background-image: url('/media/img_seria/1LG-504D12_2.jpg'); background-position: left 65%; background-repeat: no-repeat; background-size: 400px auto;"><i style="padding-left: 420px">401</i></h1>
<h2 style="color: #333; font-size: 40px;">Требуется авторизация</h2>
<h4 style="color: #666; margin: 0 0 0 30px; font-size: 20px;">Для доступа к этому ресурсу требуется авторизация.</h4>
<p style="margin-top: 55px;"><a href="/login-logout">Войти в систему</a> или <a href="/">вернуться на главную</a></p>
</div>
</body>
</html>

View File

@@ -0,0 +1,32 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>403 — Доступ запрещён</title>
<!-- Аналитика: Google Analytics 4, Yandex.Metrika, Top.Mail.Ru -->
<script src="/static/js/analytics.js" type="text/javascript"></script>
<style>
.container::before {
content: "";
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
background-image: url('/media/img_seria/1LG-504D12_2.jpg');
opacity: 0.6; /* Полупрозрачность только для картинки */
z-index: -1; /* Уводит картинку под текст */
background-position: 18% 15%;
background-repeat: no-repeat;
background-size: 200px auto;
}
</style>
</head>
<body>
<div class="container" style="margin: 10% 0 0 20%;">
<h1 style="font-size: 120px; margin: 0; color: #ccc; background-image: url('/static/img/oknardia_logo.gif'); background-position: left 65%; background-repeat: no-repeat; background-size: 400px auto;"><i style="padding-left: 420px">403</i></h1>
<h2 style="color: #333; font-size: 40px;">Доступ запрещён</h2>
<h4 style="color: #666; margin: 0 0 0 30px; font-size: 20px;">У вас нет прав для доступа к этому ресурсу. Если вы считаете это ошибкой, свяжитесь с администратором.</h4>
<p style="margin-top: 55px;"><a href="/">Вернуться на главную oknardia.ru</a></p>
</div>
</body>
</html>

View File

@@ -0,0 +1,31 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>404 — Страница не найдена</title>
<!-- Аналитика: Google Analytics 4, Yandex.Metrika, Top.Mail.Ru -->
<script src="/static/js/analytics.js" type="text/javascript"></script>
<style>
.container::before {
content: "";
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
background-image: url('/media/img_seria/1LG-504D12_2.jpg');
opacity: 0.6; /* Полупрозрачность только для картинки */
z-index: -1; /* Уводит картинку под текст */
background-position: 18% 15%;
background-repeat: no-repeat;
background-size: 200px auto;
}
</style>
</head>
<body>
<div class="container" style="margin: 10% 0 0 20%;">
<h1 style="font-size: 120px; margin: 0; color: #ccc; background-image: url('/static/img/oknardia_logo.gif'); background-position: left 65%; background-repeat: no-repeat; background-size: 400px auto;"><i style="padding-left: 420px">404</i></h1>
<h2 style="color: #333; font-size: 40px;">Страница не найдена</h2>
<h4 style="color: #666; margin: 0 0 0 30px; font-size: 20px;">К сожалению, запрашиваемая страница не существует или была удалена.</h4>
<p style="margin-top: 55px;"><a href="/">Вернуться на главную oknardia.ru</a></p>
</div>
</body>
</html>

View File

@@ -0,0 +1,29 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>413 — Файл слишком большой</title>
<style>
.container::before {
content: "";
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
background-image: url('/media/img_seria/1LG-504D12_2.jpg');
opacity: 0.6;
z-index: -1;
background-position: 18% 15%;
background-repeat: no-repeat;
background-size: 200px auto;
}
</style>
</head>
<body>
<div class="container" style="margin: 10% 0 0 20%;">
<h1 style="font-size: 120px; margin: 0; color: #ccc; background-image: url('/media/img_seria/1LG-504D12_2.jpg'); background-position: left 65%; background-repeat: no-repeat; background-size: 400px auto;"><i style="padding-left: 420px">413</i></h1>
<h2 style="color: #333; font-size: 40px;">Файл слишком большой</h2>
<h4 style="color: #666; margin: 0 0 0 30px; font-size: 20px;">Размер загружаемого файла превышает допустимый лимит (максимум 10 МБ).</h4>
<p style="margin-top: 55px;"><a href="/">Вернуться на главную oknardia.ru</a></p>
</div>
</body>
</html>

View File

@@ -0,0 +1,29 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>429 — Слишком много запросов</title>
<style>
.container::before {
content: "";
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
background-image: url('/media/img_seria/1LG-504D12_2.jpg');
opacity: 0.6;
z-index: -1;
background-position: 18% 15%;
background-repeat: no-repeat;
background-size: 200px auto;
}
</style>
</head>
<body>
<div class="container" style="margin: 10% 0 0 20%;">
<h1 style="font-size: 120px; margin: 0; color: #ccc; background-image: url('/media/img_seria/1LG-504D12_2.jpg'); background-position: left 65%; background-repeat: no-repeat; background-size: 400px auto;"><i style="padding-left: 420px">429</i></h1>
<h2 style="color: #333; font-size: 40px;">Слишком много запросов</h2>
<h4 style="color: #666; margin: 0 0 0 30px; font-size: 20px;">Вы отправляете слишком много запросов. Пожалуйста, немного подождите и попробуйте снова.</h4>
<p style="margin-top: 55px;"><a href="/">Вернуться на главную oknardia.ru</a></p>
</div>
</body>
</html>

View File

@@ -0,0 +1,31 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>500 — Внутренняя ошибка сервера</title>
<!-- Аналитика: Google Analytics 4, Yandex.Metrika, Top.Mail.Ru -->
<script src="/static/js/analytics.js" type="text/javascript"></script>
<style>
.container::before {
content: "";
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
background-image: url('/media/img_seria/1LG-504D12_2.jpg');
opacity: 0.6; /* Полупрозрачность только для картинки */
z-index: -1; /* Уводит картинку под текст */
background-position: 18% 15%;
background-repeat: no-repeat;
background-size: 200px auto;
}
</style>
</head>
<body>
<div class="container" style="margin: 10% 0 0 20%;">
<h1 style="font-size: 120px; margin: 0; color: #ccc; background-image: url('/media/img_seria/1LG-504D12_2.jpg'); background-position: left 65%; background-repeat: no-repeat; background-size: 400px auto;"><i style="padding-left: 420px">500</i></h1>
<h2 style="color: #333; font-size: 40px;">Внутренняя ошибка сервера</h2>
<h4 style="color: #666; margin: 0 0 0 30px; font-size: 20px;">На нашем сервере произошла непредвиденная ошибка. Команда разработчиков уже работает над решением проблемы.</h4>
<p style="color: #999; margin: 20px 0 0 30px; font-size: 14px;">Если проблема сохраняется, пожалуйста, свяжитесь с администратором: <a href="mailto:info@oknardia.ru">info@oknardia.ru</a></p>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,29 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>502 — Плохой шлюз</title>
<style>
.container::before {
content: "";
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
background-image: url('/media/img_seria/1LG-504D12_2.jpg');
opacity: 0.6;
z-index: -1;
background-position: 18% 15%;
background-repeat: no-repeat;
background-size: 200px auto;
}
</style>
</head>
<body>
<div class="container" style="margin: 10% 0 0 20%;">
<h1 style="font-size: 120px; margin: 0; color: #ccc; background-image: url('/media/img_seria/1LG-504D12_2.jpg'); background-position: left 65%; background-repeat: no-repeat; background-size: 400px auto;"><i style="padding-left: 420px">502</i></h1>
<h2 style="color: #333; font-size: 40px;">Плохой шлюз</h2>
<h4 style="color: #666; margin: 0 0 0 30px; font-size: 20px;">Сервер приложения временно недоступен. Мы работаем над восстановлением работоспособности.</h4>
<p style="color: #999; margin: 20px 0 0 30px; font-size: 14px;">Пожалуйста, попробуйте перезагрузить страницу через несколько минут. Если проблема сохраняется, свяжитесь с нами: <a href="mailto:info@oknardia.ru">info@oknardia.ru</a></p>
</div>
</body>
</html>

View File

@@ -0,0 +1,29 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>503 — Сервис недоступен</title>
<style>
.container::before {
content: "";
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
background-image: url('/media/img_seria/1LG-504D12_2.jpg');
opacity: 0.6;
z-index: -1;
background-position: 18% 15%;
background-repeat: no-repeat;
background-size: 200px auto;
}
</style>
</head>
<body>
<div class="container" style="margin: 10% 0 0 20%;">
<h1 style="font-size: 120px; margin: 0; color: #ccc; background-image: url('/media/img_seria/1LG-504D12_2.jpg'); background-position: left 65%; background-repeat: no-repeat; background-size: 400px auto;"><i style="padding-left: 420px">503</i></h1>
<h2 style="color: #333; font-size: 40px;">Сервис недоступен</h2>
<h4 style="color: #666; margin: 0 0 0 30px; font-size: 20px;">Сайт временно недоступен для плановых работ. Мы скоро вернёмся!</h4>
<p style="color: #999; margin: 20px 0 0 30px; font-size: 14px;">Информация об обслуживании обновляется автоматически. Спасибо за терпение!</p>
</div>
</body>
</html>

View File

@@ -0,0 +1,29 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>504 — Тайм-аут шлюза</title>
<style>
.container::before {
content: "";
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
background-image: url('/media/img_seria/1LG-504D12_2.jpg');
opacity: 0.6;
z-index: -1;
background-position: 18% 15%;
background-repeat: no-repeat;
background-size: 200px auto;
}
</style>
</head>
<body>
<div class="container" style="margin: 10% 0 0 20%;">
<h1 style="font-size: 120px; margin: 0; color: #ccc; background-image: url('/media/img_seria/1LG-504D12_2.jpg'); background-position: left 65%; background-repeat: no-repeat; background-size: 400px auto;"><i style="padding-left: 420px">504</i></h1>
<h2 style="color: #333; font-size: 40px;">Тайм-аут шлюза</h2>
<h4 style="color: #666; margin: 0 0 0 30px; font-size: 20px;">Сервер приложения слишком долго отвечает на запрос. Это может быть перегрузка или технический сбой.</h4>
<p style="color: #999; margin: 20px 0 0 30px; font-size: 14px;">Попробуйте перезагрузить страницу через несколько минут. Если проблема повторится, свяжитесь с поддержкой: <a href="mailto:info@oknardia.ru">info@oknardia.ru</a></p>
</div>
</body>
</html>

View File

@@ -0,0 +1,29 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Технические работы</title>
<style>
.container::before {
content: "";
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
background-image: url('/media/img_seria/1LG-504D12_2.jpg');
opacity: 0.6;
z-index: -1;
background-position: 18% 15%;
background-repeat: no-repeat;
background-size: 200px auto;
}
</style>
</head>
<body>
<div class="container" style="margin: 10% 0 0 20%;">
<h1 style="font-size: 80px; margin: 0; color: #ccc; background-image: url('/media/img_seria/1LG-504D12_2.jpg'); background-position: left 65%; background-repeat: no-repeat; background-size: 400px auto;"><i style="padding-left: 420px"></i></h1>
<h2 style="color: #333; font-size: 40px;">Технические работы</h2>
<h4 style="color: #666; margin: 0 0 0 30px; font-size: 20px;">Приносим извинения. В данный момент сайт проходит техническое обслуживание. Мы скоро вернёмся!</h4>
<p style="margin-top: 55px;"><a href="/">Вернуться на главную oknardia.ru</a></p>
</div>
</body>
</html>

View File

@@ -242,3 +242,66 @@ def get_address(request: HttpRequest) -> HttpResponse:
'ticks': float(time.perf_counter() - time_start),
})
return render(request, "popup/popup_show_apartment_variants.html", to_template)
# ============================================================================
# ОБРАБОТЧИКИ ОШИБОК ДЛЯ ТЕСТИРОВАНИЯ В DEBUG РЕЖИМЕ
# ============================================================================
# Используется в urls.py при DEBUG=True для тестирования верстки страниц ошибок.
# Позволяет визуально проверить, как выглядят страницы 400, 403, 404 и 500
# без необходимости искусственно вызывать реальные ошибки.
def handler400(request: HttpRequest, exception=None) -> HttpResponse:
"""Отображает страницу ошибки 400 (Bad Request).
Используется только в DEBUG режиме для тестирования верстки.
:param request: входящий http-запрос
:param exception: исключение (если есть)
:return response: исходящий http-ответ с кодом 400
"""
response = render(request, "error/400.html", {})
response.status_code = 400
return response
def handler403(request: HttpRequest, exception=None) -> HttpResponse:
"""Отображает страницу ошибки 403 (Forbidden).
Используется только в DEBUG режиме для тестирования верстки.
:param request: входящий http-запрос
:param exception: исключение (если есть)
:return response: исходящий http-ответ с кодом 403
"""
response = render(request, "error/403.html", {})
response.status_code = 403
return response
def handler404(request: HttpRequest, exception=None) -> HttpResponse:
"""Отображает страницу ошибки 404 (Not Found).
Используется только в DEBUG режиме для тестирования верстки.
:param request: входящий http-запрос
:param exception: исключение (если есть)
:return response: исходящий http-ответ с кодом 404
"""
response = render(request, "error/404.html", {})
response.status_code = 404
return response
def handler500(request: HttpRequest) -> HttpResponse:
"""Отображает страницу ошибки 500 (Internal Server Error).
Используется только в DEBUG режиме для тестирования верстки.
:param request: входящий http-запрос
:return response: исходящий http-ответ с кодом 500
"""
response = render(request, "error/500.html", {})
response.status_code = 500
return response

View File

@@ -1,5 +1,5 @@
# Маркетплейс-агрегатор цен на установку пластиковых и деревянных окон — ОКНАРДИЯ
# robots.txt последняя версия: 2026-05-15
# robots.txt последняя версия: 2026-05-20
User-Agent: *
Allow: /
@@ -10,6 +10,9 @@ Disallow: /*?*token*
Disallow: /*.json$
Disallow: /.*\.(js|css)$ # CSS и JS обслуживаются отдельно через CDN
# Параметры, которые не влияют на смысловое содержимое
Clean-param: page-back /
# Быстрые краулеры
User-agent: YandexBot
Crawl-delay: 15