Merge pull request 'Provide custom error pages' (#114) from 20-error-pages into main
All checks were successful
Build and Deploy Staging / build (push) Successful in 1m18s
Tests / test (push) Successful in 24s
Build and Deploy Staging / deploy (push) Successful in 8s

Reviewed-on: #114
This commit is contained in:
Tobias Kunze 2025-06-23 09:30:58 +00:00
commit 6e88969677
9 changed files with 97 additions and 1 deletions

View file

@ -0,0 +1,9 @@
{% extends "error_base.html" %}
{% block title %}403 - Access Forbidden{% endblock title %}
{% block error_alt %}Access Forbidden{% endblock error_alt %}
{% block error_title %}Access Forbidden{% endblock error_title %}
{% block error_message %}You are not authorized to access this page.{% endblock error_message %}

View file

@ -0,0 +1,9 @@
{% extends "error_base.html" %}
{% block title %}404 - Page Not Found{% endblock title %}
{% block error_alt %}Not Found{% endblock error_alt %}
{% block error_title %}Page Not Found{% endblock error_title %}
{% block error_message %}The page you are looking for could not be found.{% endblock error_message %}

View file

@ -0,0 +1,9 @@
{% extends "error_base.html" %}
{% block title %}500 - Server Error{% endblock title %}
{% block error_alt %}Server Error{% endblock error_alt %}
{% block error_title %}Server Error{% endblock error_title %}
{% block error_message %}The website is currently unavailable. Please try again later or contact support.{% endblock error_message %}

View file

@ -0,0 +1,33 @@
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}Error{% endblock title %} - Servala</title>
<link rel="shortcut icon"
href="data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2033%2034'%20fill-rule='evenodd'%20stroke-linejoin='round'%20stroke-miterlimit='2'%20xmlns:v='https://vecta.io/nano'%3e%3cpath%20d='M3%2027.472c0%204.409%206.18%205.552%2013.5%205.552%207.281%200%2013.5-1.103%2013.5-5.513s-6.179-5.552-13.5-5.552c-7.281%200-13.5%201.103-13.5%205.513z'%20fill='%23435ebe'%20fill-rule='nonzero'/%3e%3ccircle%20cx='16.5'%20cy='8.8'%20r='8.8'%20fill='%2341bbdd'/%3e%3c/svg%3e"
type="image/x-icon">
<link rel="stylesheet" href="{% static 'mazer/compiled/css/app.css' %}">
<link rel="stylesheet" href="{% static 'mazer/compiled/css/error.css' %}">
</head>
<body>
<script src="{% static 'mazer/static/js/initTheme.js' %}"></script>
<div id="error">
<div class="error-page container">
<div class="col-md-8 col-12 offset-md-2">
<div class="text-center">
<img class="img-error"
src="{% static 'img/sir-vala-notext.png' %}"
alt="Sir Vala - {% block error_alt %}Error{% endblock error_alt %}"
style="max-width: 300px;
margin-bottom: 2rem">
<h1 class="error-title">{% block error_title %}Error{% endblock error_title %}</h1>
<p class="fs-5 text-gray-600">{% block error_message %}An error occurred.{% endblock error_message %}</p>
<a href="/" class="btn btn-lg btn-outline-primary mt-3">Go Home</a>
</div>
</div>
</div>
</div>
</body>
</html>

View file

@ -1,3 +1,4 @@
from django.conf import settings
from django.urls import include, path from django.urls import include, path
from django.views.generic import RedirectView from django.views.generic import RedirectView
@ -64,4 +65,18 @@ urlpatterns = [
), ),
), ),
path("", RedirectView.as_view(pattern_name="frontend:profile"), name="index"), path("", RedirectView.as_view(pattern_name="frontend:profile"), name="index"),
# Error page URLs available in all environments
path(
"error404/",
views.custom_404,
{"exception": Exception("Test 404")},
name="error_404",
),
path(
"error403/",
views.custom_403,
{"exception": Exception("Test 403")},
name="error_403",
),
path("error500/", views.custom_500, name="error_500"),
] ]

View file

@ -1,5 +1,5 @@
from .auth import LogoutView from .auth import LogoutView
from .generic import IndexView, ProfileView from .generic import IndexView, ProfileView, custom_403, custom_404, custom_500
from .organization import ( from .organization import (
OrganizationCreateView, OrganizationCreateView,
OrganizationDashboardView, OrganizationDashboardView,
@ -29,4 +29,7 @@ __all__ = [
"ServiceListView", "ServiceListView",
"ServiceOfferingDetailView", "ServiceOfferingDetailView",
"ProfileView", "ProfileView",
"custom_404",
"custom_403",
"custom_500",
] ]

View file

@ -1,4 +1,5 @@
from django.conf import settings from django.conf import settings
from django.shortcuts import render
from django.urls import reverse_lazy from django.urls import reverse_lazy
from django.utils.functional import cached_property from django.utils.functional import cached_property
from django.views.generic import TemplateView from django.views.generic import TemplateView
@ -42,3 +43,15 @@ class ProfileView(HtmxUpdateView):
def form_valid(self, form): def form_valid(self, form):
form.save() form.save()
return super().form_valid(form) return super().form_valid(form)
def custom_404(request, exception):
return render(request, "404.html", status=404)
def custom_403(request, exception):
return render(request, "403.html", status=403)
def custom_500(request):
return render(request, "500.html", status=500)

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

View file

@ -26,3 +26,8 @@ urlpatterns = [
if settings.DEBUG: if settings.DEBUG:
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
# Custom error handlers
handler404 = "servala.frontend.views.custom_404"
handler403 = "servala.frontend.views.custom_403"
handler500 = "servala.frontend.views.custom_500"