diff --git a/cadpoint/cadpoint/urls.py b/cadpoint/cadpoint/urls.py index 3b08a62..ac88c02 100644 --- a/cadpoint/cadpoint/urls.py +++ b/cadpoint/cadpoint/urls.py @@ -57,6 +57,8 @@ urlpatterns = [ ] handler404 = 'web.views.handler404' +handler400 = 'web.views.handler400' +handler403 = 'web.views.handler403' handler500 = 'web.views.handler500' if settings.DEBUG: diff --git a/cadpoint/templates/400.html b/cadpoint/templates/400.html new file mode 100644 index 0000000..77c88b1 --- /dev/null +++ b/cadpoint/templates/400.html @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + CADpoint.ru - http 400 error + + + + + + +
+
+
+ cadpoint.ru - http 400 error +
запрос получился некорректным.
+Проверьте адрес, параметры или форму и попробуйте ещё раз.
+Вернуться на главную
+
+
+
+ + + diff --git a/cadpoint/templates/401.html b/cadpoint/templates/401.html new file mode 100644 index 0000000..0f3becb --- /dev/null +++ b/cadpoint/templates/401.html @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + CADpoint.ru - http 401 error + + + + + + +
+
+
+ cadpoint.ru - http 401 error +
для этой страницы нужен вход в систему.
+Если у вас есть доступ (и вы знаете где он находится) — войдите и попробуйте ещё раз.
+
+
+
+ + + diff --git a/cadpoint/templates/403.html b/cadpoint/templates/403.html new file mode 100644 index 0000000..ce0fca3 --- /dev/null +++ b/cadpoint/templates/403.html @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + CADpoint.ru - http 403 error + + + + + + +
+
+
+ cadpoint.ru - http 403 error +
доступ к этой странице ограничен.
+Проверьте права доступа или обратитесь к админис­тратору, если считаете, что это ошибка.
+
+
+
+ + + diff --git a/cadpoint/templates/404.html b/cadpoint/templates/404.html index b76f897..ef1fbc1 100644 --- a/cadpoint/templates/404.html +++ b/cadpoint/templates/404.html @@ -6,27 +6,28 @@ - - + + CADpoint.ru - http 404 error - - - + + +
- cadpoint.ru - http 404 error -
попробуйте начать просмотр сайта с главной страницы...
+
похоже, такой страницы или картинки больше нет.
+Если ссылка старая или адрес был введён вручную, вернитесь на главную и попробуйте ещё раз…
- \ No newline at end of file + diff --git a/cadpoint/templates/413.html b/cadpoint/templates/413.html new file mode 100644 index 0000000..0b9129a --- /dev/null +++ b/cadpoint/templates/413.html @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + CADpoint.ru - http 413 error + + + + + + +
+
+
+ cadpoint.ru - http 413 error +
запрос оказался слишком большим.
+Попробуйте уменьшить объём данных или загрузить файл поменьше.
+
+
+
+ + + diff --git a/cadpoint/templates/429.html b/cadpoint/templates/429.html new file mode 100644 index 0000000..7c48e85 --- /dev/null +++ b/cadpoint/templates/429.html @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + CADpoint.ru - http 429 error + + + + + + +
+
+
+ cadpoint.ru - http 429 error +
слишком много запросов за короткое время.
+Подождите немного и попробуйте снова.
+
+
+
+ + + diff --git a/cadpoint/templates/500.html b/cadpoint/templates/500.html index ed08178..d7ab5ec 100644 --- a/cadpoint/templates/500.html +++ b/cadpoint/templates/500.html @@ -6,26 +6,27 @@ - - + + CADpoint.ru - http 500 error - - - + + +
- cadpoint.ru - http 500 error -
подождите, скоро все починят...
+ cadpoint.ru - http 500 error +
подождите, скоро всё починят…
+Если ошибка повторяется, серверу нужен небольшой ремонт.
- \ No newline at end of file + diff --git a/cadpoint/templates/502.html b/cadpoint/templates/502.html new file mode 100644 index 0000000..7336f46 --- /dev/null +++ b/cadpoint/templates/502.html @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + CADpoint.ru - http 502 error + + + + + + +
+
+
+ cadpoint.ru - http 502 error +
сервис временно недоступен.
+Попробуйте открыть страницу чуть позже.
+
+
+
+ + + diff --git a/cadpoint/templates/503.html b/cadpoint/templates/503.html new file mode 100644 index 0000000..2779c19 --- /dev/null +++ b/cadpoint/templates/503.html @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + CADpoint.ru - http 503 error + + + + + + +
+
+
+ cadpoint.ru - http 503 error +
сервис временно недоступен.
+Скоро всё должно заработать снова — просто подождите немного.
+
+
+
+ + + diff --git a/cadpoint/templates/504.html b/cadpoint/templates/504.html new file mode 100644 index 0000000..84b38c3 --- /dev/null +++ b/cadpoint/templates/504.html @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + CADpoint.ru - http 504 error + + + + + + +
+
+
+ cadpoint.ru - http 504 error +
сервер отвечает слишком долго.
+Подождите немного и попробуйте снова.
+
+
+
+ + + diff --git a/cadpoint/templates/base.jinja2 b/cadpoint/templates/base.jinja2 index ad39155..66da933 100644 --- a/cadpoint/templates/base.jinja2 +++ b/cadpoint/templates/base.jinja2 @@ -5,7 +5,7 @@ - + {% block page_title %}CADPOINT.RU{% endblock %} diff --git a/cadpoint/web/tests.py b/cadpoint/web/tests.py index 31a7e8c..26ec77b 100644 --- a/cadpoint/web/tests.py +++ b/cadpoint/web/tests.py @@ -13,7 +13,12 @@ from web.legacy_links import build_canonical_url, replace_legacy_links from web.models import TbContent +# Этот файл смешивает два типа проверок: +# - простые тесты чистой логики без базы данных (`SimpleTestCase`), +# - интеграционные Django-тесты с базой и HTTP-клиентом (`TestCase`). class LegacyLinksTests(SimpleTestCase): + # `SimpleTestCase` подходит для функций, которые не ходят в базу и не + # требуют полноценного HTTP-запроса: здесь мы просто проверяем строки. def test_build_canonical_url_without_slug(self): self.assertEqual(build_canonical_url(123, ''), '/item/123-') @@ -42,6 +47,7 @@ class LegacyLinksTests(SimpleTestCase): self.assertEqual(len(matches), 1) +# Эти тесты тоже без базы: проверяем очистку HTML и подготовку slug'ов. class SafeHtmlSpecialSymbolsTests(SimpleTestCase): def test_strips_html_tags_and_decodes_entities(self): text = '

«Привет мир» ­

' @@ -54,6 +60,7 @@ class SafeHtmlSpecialSymbolsTests(SimpleTestCase): self.assertEqual(clean_text_to_slug('₽ € $ ₴ ₿'), 'content') +# Здесь проверяем форму админки: её поля, виджеты и виртуальные настройки. class AdminTypographFormTests(SimpleTestCase): def test_admin_form_exposes_virtual_typograph_fields(self): form = AdminContentForm() @@ -100,7 +107,11 @@ class AdminTypographFormTests(SimpleTestCase): self.assertEqual(str(item), '007: «Привет мир»') +# В этих тестах уже нужна база и `client`, потому что мы проверяем Django-views +# и JSON-ответы как реальные запросы из браузера. class TagAutocompleteTests(TestCase): + # `TestCase` поднимает тестовую БД, а `client` умеет делать полноценные запросы + # к Django, как будто их отправил браузер. def setUp(self): user_model = get_user_model() self.user = user_model.objects.create_superuser( @@ -150,6 +161,7 @@ class TagAutocompleteTests(TestCase): self.assertEqual(payload['pagination']['more'], False) +# Страница со всеми тегами — тоже обычный Django-response, поэтому тут `TestCase`. class AllTagsPageTests(TestCase): def setUp(self): user_model = get_user_model() @@ -207,6 +219,7 @@ class AllTagsPageTests(TestCase): self.assertNotContains(response, 'onclick="CookieAcceptDate') +# Здесь проверяем поведение страницы тега, включая пустое состояние. class TagEmptyStateTests(TestCase): def setUp(self): self.item = TbContent.objects.create( @@ -242,6 +255,7 @@ class TagEmptyStateTests(TestCase): self.assertContains(response, 'не найден или был переименован') +# Тут мы проверяем модель и `save()`: slug, типограф, счётчик просмотров и SEO-поля. class TypographTests(TestCase): def test_save_generates_slug_from_clean_text(self): item = TbContent(szContentHead='Привет мир') @@ -410,6 +424,7 @@ class TypographTests(TestCase): self.assertNotContains(response, 'None') +# Это тесты карты сайта: проверяем, что в XML попадают только публичные страницы. class SitemapTests(TestCase): def setUp(self): self.published = TbContent.objects.create( @@ -444,6 +459,8 @@ class SitemapTests(TestCase): self.assertNotContains(response, 'skrytaya-statya') +# Для error-handlers удобно использовать `RequestFactory`: мы сами создаём +# request и вызываем функцию-обработчик напрямую, без прохода через URL-роутинг. class ErrorHandlersTests(SimpleTestCase): def setUp(self): self.factory = RequestFactory() @@ -469,7 +486,7 @@ class ErrorHandlersTests(SimpleTestCase): self.assertEqual(response.status_code, 403) self.assertContains(response, 'CADpoint.ru - http 403 error', status_code=403) self.assertContains(response, '', status_code=403) - self.assertContains(response, 'доступ к этой странице ограничен.', status_code=403) + self.assertContains(response, 'доступ к этой странице ограничен.', status_code=403) def test_handler404_renders_modern_template(self): response = self.client.get('/no-such-page/') @@ -477,7 +494,7 @@ class ErrorHandlersTests(SimpleTestCase): self.assertEqual(response.status_code, 404) self.assertContains(response, 'CADpoint.ru - http 404 error', status_code=404) self.assertContains(response, '', status_code=404) - self.assertContains(response, 'похоже, такой страницы больше нет.', status_code=404) + self.assertContains(response, 'похоже, такой страницы или картинки больше нет.', status_code=404) def test_handler500_renders_modern_template(self): from web.views import handler500 diff --git a/cadpoint/web/views.py b/cadpoint/web/views.py index a72292c..0ae3f84 100644 --- a/cadpoint/web/views.py +++ b/cadpoint/web/views.py @@ -26,6 +26,30 @@ def handler404(request, exception: str): return response +def handler400(request, exception: Exception): + """ Обработчик ошибки 400 + + :param request: + :param exception: + :return: response: + """ + response = render(request, "400.html", {"MSG": exception}) + response.status_code = 400 + return response + + +def handler403(request, exception: Exception): + """ Обработчик ошибки 403 + + :param request: + :param exception: + :return: response: + """ + response = render(request, "403.html", {"MSG": exception}) + response.status_code = 403 + return response + + def handler500(request): """ Обработчик ошибки 500 diff --git a/public/static/README.md b/public/static/README.md new file mode 100644 index 0000000..8fc3bb6 --- /dev/null +++ b/public/static/README.md @@ -0,0 +1,18 @@ +# СТАТИКА + +Эта папка предназначена для хранения статических файлов, таких как изображения, стили CSS и JavaScript файлы. +Папка будет внутри контейнера, а файлы внутри папки будут доступны с помощью gunicorn и whitenoise на хосте. + +Но в случае сбоя контейнера, ошибок Djанго и ошибок 404 при доступе в media (которые будут в папке `media` на +внешнем хосте с доступом через nginx), то эти файлы могут стать недоступны. Таким образом, файлы необхдимые +для отображения кастовых страниц ошибок 400, 403, 404, 500 и других должны быть скопированы на внешний хост, +в папку `media/_error` в момент запуска контейнера (с помощью `entrypoint.sh` или инструкций `command` +в `docker-compose.yml`) + +. Вот список этих файлов (путь указан относительно папки `static`): +* svgs/favicon.svg +* img/favicon.png +* img/favicon.ico +* svgs/xxx-error.svg +* svgs/404-error.svg +* svgs/500-error.svg \ No newline at end of file diff --git a/public/static/svgs/xxx-error.svg b/public/static/svgs/xxx-error.svg new file mode 100644 index 0000000..b6c6e7e --- /dev/null +++ b/public/static/svgs/xxx-error.svg @@ -0,0 +1 @@ + \ No newline at end of file