3

I need to create a multisite configuration that let me use the same domain for different sites.

Some examples of what URLs I need to achieve:

subdomain.example.com  (Home for all sites)
|
---subdomain.example.com/common-page/  (Common page for all sites)
|
---subdomain.example.com/common-page-2/  (Common page for all sites)
|
--- subdomain.example.com/news/  (News from all sites)
|
--- subdomain.example.com/site-1/  (Redirects to Home subdomain.example.com)
|
--- subdomain.example.com/site-2/  (Redirects to Home subdomain.example.com)
|
--- subdomain.example.com/site-1/news/  (Site 1 news)
|
--- subdomain.example.com/site-3/news/  (Site 3 news)
|
--- subdomain.example.com/site-1/contact/  (Contact form site 1)
|
--- subdomain.example.com/site-3/contact/  (Contact form site 3)

I could create this structure on just one site, but it would then be a pain to manage it on the wagtail admin.

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
Cristián
  • 363
  • 3
  • 13
  • 1
    In Wagtail's terminology, sites and domains are exactly the same thing, so "multiple sites on the same domain" doesn't make sense. What *exactly* do you want Wagtail to do here which is different from a single-site installation? (Bear in mind that Wagtail will always show all your pages as a single tree, regardless of how many sites / domains you have configured.) – gasman Aug 02 '17 at 19:14
  • The difference from a single site installation is that every site have their own contact form, news and events. Right now I have the 3 sites configured and explorer tree shows me the 3 sites making it much easier to manage, but the pages arent accesible (error 404) on 2 of the sites – Cristián Aug 02 '17 at 19:32
  • OK, let me rephrase my question: what's stopping you from creating the pages you want, as children of the homepage, so that their position in the page tree matches the URLs that you want? – gasman Aug 03 '17 at 10:30
  • 1
    The easier site management is the only thing that is stopping me creating just 1 site (3 sites with diferent news/events vs 1 site with 3 subpages news/events). But it seems is rather a small user experience improvement for the effort needed on the backend to achieve this as I intended to. Anyway, thanks gasman for making this clearer to me. – Cristián Aug 03 '17 at 17:10

1 Answers1

1

Answering an old question for future enquirers. @gasman has nailed the issue with this ask in his comment above:

In Wagtail's terminology, sites and domains are exactly the same thing, so "multiple sites on the same domain" doesn't make sense.

However, I was able to work around this using the following steps.

I needed this kind of arrangement so that different site-wide settings could be used for mainsite.com and mainsite.com/subsite (example names).

While I can always enforce different settings for different parts of my website in the code I've written, I wanted this to work for third-party packages as well such as wagtailmenus etc.

E.g. I wanted the menu-items for all pages on mysite.com to be different from those for all pages under and including mainsite.com/subsite.

Note that this is a crude approach, and there can be unforeseen issues with this. But, so far, it has worked fine for me.

  1. Create a new site in Wagtail admin for your subsite.
    Use the same hostname as was used for the mainsite, but add a dot in the end for satisfying uniqueness. We'll not use this hostname anyway.
    Also, use the same root page as mainsite's. This is for generating the URLs correctly.

  2. Create a small middleware:

    if request.path.startswith('/subsite'):
        # find subsite and mainsite using Site.objects.filter(site_name='') queries
        subsite.hostname = mainsite.hostname
        request._wagtail_site = subsite
    

    This will make sure that all requests coming to the subsite get their specific _wagtail_site attribute but with the correct hostname. This will let your code and all other code in third-party packages to determine the site as subsite. But, if a third-party package uses Django's site instead of Wagtail's Site, I'm not sure if this will still work.

  3. Generally, you would not want the subsite to be set as default website. To enforce this, include the following in any of your apps' admin.py (I added some extra validations as well):

    def clean_subsite(self):
        instance = self
        if instance.site_name != 'Subsite': return
        super(Site, self).clean()
        if instance.is_default_site:
            raise ValidationError({'is_default_site': ["'Subsite' cannot be made the default website."]})
    
        mainsite = Site.objects.filter(site_name='Mainsite').first()
        if not mainsite:
            raise ValidationError({'hostname': ["'Mainsite' must exist before saving 'Subsite'."]})
    
        if instance.hostname != (mainsite.hostname + '.'):
            raise ValidationError({'hostname': ["Hostname for Subsite is just a placeholder (Subsite uses the same domain as Mainsite does)." +
            " Use the Mainsite's hostname with a '.' as suffix for satisfying uniqueness constraint."]})
    
    from wagtail.core.models import Site
    Site.add_to_class("clean", clean_subsite)
    

    As the Site filter queries above are using site_name='', do not change the names of Mainsite and Subsite in the Admin (without modifying these queries in the code).

  4. Lastly, be warned that the query Page.objects.in_site() will work incorrectly for both mainsite and subsite.
    Either do not use in_site(), or override it. This function uses:

    self.descendant_of(site.root_page, inclusive=True)
    

    For mainsite, we need to exclude the descendants of subsite's root page. For subsite, we need to include only the descendants of subsite's root page.

manisar
  • 103
  • 1
  • 7