5

I'm trying to get two different Wagtail sites to have their own 404 pages, but there does not appear to be a way to specify which page to use as 404 page in a "site" config in the wagtail "settings" => "sites" section, and I can't seem to get the correct 404 to be loaded when I put them into the app directories involved:

codebase/
  ./__init__.py
  ./manage.py
  ./apps/
     ./settings.py
     ./urls.py
     ...
     ./django-app-1/
     ./django-app-2/
     ./templates/
        ./404.html
     ./mainsite/
        ./migrations/
        ./static/
        ./templates/
           ./mainsite/
           ./404.html (this 404 always gets used)
     ./spinoff/
        ./migrations/
        ./static/
        ./templates/
           ./spinoff/
           ./404.html (this file never gets used)

So in INSTALLED_APPS we have:

INSTALLED_APPS = [
  ...django apps...
  ...wagtail apps...

  'apps.mainsite',
  'apps.spinoff',
]

In this, the main site has the vast bulk of all the page types, and the spinoff site, which runs on a different domain, uses those page types by importing them from apps.mainsite.

In Wagtail we have two pages that work as root: a Homepage that is a mainsite Page type, and a Spinoff Homepage that is a spinof Page type that inherits from the mainsite's page type.

In the sites settings, we have one site entry that points to mainsite.com, with the main Homepage set as Root, and another site entry that points to spinoff.com, with the spinoff homepage set as root.

For both of these sites, an non-existent url request leads to the main site's 404.html getting used, so the question is: how do we make non-existent urls on the spinoff domain resolve to the spinoff's 404.html instead?

Mike 'Pomax' Kamermans
  • 49,297
  • 16
  • 112
  • 153
  • For reference an issue has been raised for this question as it appears to be missing in the documentation. https://github.com/wagtail/wagtail/issues/5360 – LB Ben Johnston Jun 09 '19 at 21:15
  • That reference being me: I filed that, after this question didn't get an answer in the usual time wagtail questions do =) – Mike 'Pomax' Kamermans Jun 09 '19 at 22:46
  • Yeah, it is a bit of a tricky one to get to a solid solution for, I put some more notes on the Github issue. Not sure on documentation being a solution though, maybe a simple recipe (like Dan's solution below), but it might need a code enhancement to make this kind of thing easier out of the box. – LB Ben Johnston Jun 10 '19 at 22:17
  • the wagtail documentation is pretty decent on giving examples, so for a specialised "things you need to consider when using multi-site setups" text, a concrete example would most certainly be useful, and fitting. The ideal solution, of course, is this becomes a thing you set in the `sites` settings themselves: pick a root page _and_ pick a 404 page. – Mike 'Pomax' Kamermans Jun 11 '19 at 01:32

1 Answers1

5

Since Wagtail is built on Django, you can customize the error view. Wagtail's core.view.serve calls core.models.page.route, and if the page route isn't found, then it raises Http404. Therefore, in urls.py you would put:

from yourapp.views import custom404_view

handler404 = 'yourapp.views.custom404_view'

And in views.py:

from django.http import HttpResponseNotFound

def custom404_view(request, exception):       
    return HttpResponseNotFound('<h1>{}</h1>'.format(request.site))

What I've shown above returns the Wagtail site to illustrate that the site is available in the view, so in your case, just return your HTML conditionally based upon the site.

Dan Swain
  • 2,910
  • 1
  • 16
  • 36
  • No, because wagtail sites can be a mix of any page type: the same model can be used to make two difference pages, that define two different sites, so you can't add that handler to the model, and you can't add it to the url patterns either, because Wagtail manages and autogenerates all its own urls. – Mike 'Pomax' Kamermans Jun 10 '19 at 14:52
  • I've added more detail to my answer. Please take a look again and would appreciate reconsideration of the down vote. – Dan Swain Jun 10 '19 at 17:17
  • As per the bounty: can you turn this into a documentation PR against wagtail's docs repo? Because wagtail doesn't use `views.py` files, nor `urls.py` beyond the base urls.py, So this explanation relies on people understanding concepts that don't apply when you're using wagtail (even if under the hood, they do). – Mike 'Pomax' Kamermans Jun 10 '19 at 17:53
  • 1
    I would be glad to (I highly value good documentation and have had a fair number of small pull requests approved in the Wagtail documentation). Hopefully the Wagtail maintainers will approve this PR. One thing to keep in mind - the Wagtail maintainers don't want to see Django docs repeated in their documentation, so my PR will reference the Django docs where appropriate - but I will explain the need to create a views.py file in an app. I'll plan to get the PR submitted this evening. – Dan Swain Jun 10 '19 at 18:23
  • I will keep an eye out for that PR :) – LB Ben Johnston Jun 10 '19 at 22:18
  • 1
    I've submitted a PR to cover this solution in the Wagtail docs: https://github.com/wagtail/wagtail/pull/5375. In regard to your thought on picking a root page *and* a 404 page, I'm very interested in Wagtail being full multi-tenant. In preparation for this, I've started using a *themes* folder. The *themes* folder is at the first level in the project and within it are folders that each hold all the assets for a particular theme. In my ideal world, you would associate a theme with a site. – Dan Swain Jun 12 '19 at 02:04
  • That's awesome; thanks so much for the effort, answer accepted =) – Mike 'Pomax' Kamermans Jun 13 '19 at 16:49
  • This does not appear to work any more. Testing with Django 3.2 and Wagtail 2.16.2 - any assignment to handler404 results in 500 error. Any thoughts? – michela Jul 20 '22 at 13:57