Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom 404 #375

Merged
merged 1 commit into from
Nov 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions apps/core/models/home.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
from django.conf import settings
from django.db import models
from django.http.response import Http404
from wagtail.admin.panels import FieldPanel
from wagtail.fields import StreamField
from wagtail.models import Page

from ..blocks import HOME_BLOCKS
from ..views import Custom404


class HomePage(Page):
Expand All @@ -23,3 +26,41 @@ class HomePage(Page):
FieldPanel("introduction"),
FieldPanel("sections"),
]

def route(self, request, path_components):
try:
return super().route(request, path_components)
except Http404:
raise Custom404(
fallback_pages=self.get_fallback_pages(request, path_components)
)

def get_fallback_pages(self, request, path_components):
# No fallback for main locale.
if (language_code := self.locale.language_code) == settings.LANGUAGE_CODE:
return []

# Work out translations of the page requested corresponding to:
# 1. Same version but in english (if language requested isn't english)
# 2. Same language using latest version (if version requested isn't the latest)
# 3. Latest version in English
language, version = language_code.rsplit("-", maxsplit=1)
codes = {language, "en"}
versions = {version, "latest"}
possible_language_codes = [
f"{code}-{version}" for code in codes for version in versions
]
translations = self.get_translations(inclusive=False).filter(
locale__language_code__in=possible_language_codes
)

fallback_pages = []
for page in translations:
try:
result = Page.route(page, request, path_components)
except Http404:
continue
else:
fallback_pages.append(result.page)

return fallback_pages
13 changes: 12 additions & 1 deletion apps/core/templates/404.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{% extends "base.html" %}
{% load i18n %}
{% load i18n wagtailcore_tags %}

{% block title %}{% trans 'Page not found' %}{% endblock %}

Expand All @@ -9,6 +9,17 @@ <h1 class="error-page__heading heading heading--display">{% trans 'Page not foun

<h2 class="error-page__sub-heading">{% trans 'Sorry, this page could not be found.' %}</h2>

{% if fallback_pages %}
<h3 class="error-page__sub-heading">{% trans 'Try:' %}</h3>
<ul>
{% for page in fallback_pages %}
<li>
<h4><a href="{% pageurl page %}">{{ page }} - {{ page.locale }}</a></h4>
</li>
{% endfor %}
</ul>
{% endif %}

<svg class="error-page__icon" aria-hidden="true" viewBox="0 0 47 57" aria-hidden="true"><path d="M37.034 2.04s-4.18-1.262-5.975 0c-2.643 1.858 1.168.815-1.681 4.408-2.073 2.605-2.044 5.325-.713 8.858 10.201-.858 12.278 4.85 12.278 4.85l-1.58-6.624 2.889-4.278c-.381-4.732-4.396-7.04-5.218-7.214z" fill="#fff"/><path d="M29.958 16.705l.829-1.431c-1.502-1.167-2.538-2.969-2.538-5.09 0-3.498 2.745-6.307 6.163-6.307.88 0 1.657.159 2.382.477.363-.53.725-1.166 1.088-1.961C36.38 1.385 34.567.855 32.652.855c-5.387 0-9.789 4.453-9.789 10.019 0 5.513 4.35 10.018 9.788 10.018 1.606 0 2.33-.424 2.538-1.113l-5.23-3.074zM42.23 9.284l-2.433 3.71h6.577l-4.143-3.71zM38.296 9.602c.686 0 1.243-.57 1.243-1.273 0-.702-.557-1.272-1.243-1.272-.687 0-1.243.57-1.243 1.272 0 .703.556 1.273 1.243 1.273z"/><path d="M33.208 18.39c-1.043 1.896-3.176 5.806-3.362 6.28L15.123 38.888l15.883-2.606 6.956-13.389-4.754-4.502z" fill="#fff" stroke="#000"/><path d="M41.869 22.642c0-5.407-4.298-9.86-9.633-9.86-2.02 0-3.935.636-5.49 1.75l-2.589-8.535L4.582 40.505l5.696-1.484L.283 56.78l8.442-2.862 3.21-11.026c3.263.159 26.05.689 29.675-18.235v-.053c.052-.371.155-.742.207-1.113h-.052c.052-.318.104-.583.104-.848zM20.118 36.106l.414-.318C33.324 31.97 33.894 22.96 33.894 22.96l2.175-.742c-2.175 11.609-15.951 13.888-15.951 13.888z"/></svg>
</div>
{% endblock %}
16 changes: 16 additions & 0 deletions apps/core/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from django.http import HttpResponseNotFound
from django.http.response import Http404
from django.template import loader


class Custom404(Http404):
def __init__(self, *args, fallback_pages=None, **kwargs):
super().__init__(*args, **kwargs)
self.fallback_pages = fallback_pages


def page_not_found(request, exception):
context = {"fallback_pages": getattr(exception, "fallback_pages", None)}
template = loader.get_template("404.html")
body = template.render(context, request)
return HttpResponseNotFound(body)
3 changes: 3 additions & 0 deletions apps/guide/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,6 @@
path("jsi18n/", JavaScriptCatalog.as_view(), name="javascript-catalog"),
path("", include(wagtail_urls)),
)


handler404 = "apps.core.views.page_not_found"