Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the correct way to include subdomains to the Django sitemap urls?

I have my development site (localhost.com 'as on the development machine').

This domain has got two subdomains, developer and blog.

The url configuration for sitemaps are,

from django.contrib.sitemaps.views import sitemap, index as sitemap_index

url(r'^sitemap\.xml$', sitemap_index, {'sitemaps': sitemaps},
    name='django.contrib.sitemaps.views.sitemap'),

url(r'^sitemap-(?P<section>.+)\.xml', sitemap, {'sitemaps': sitemaps}),

when creating sitemaps with sitemap index, The site maps are created as

<sitemap>
<loc>http://localhost.com/sitemap-blog.xml?p=2</loc>
</sitemap>
<sitemap>
<loc>http://localhost.com/sitemap-blog.xml?p=3</loc>
</sitemap>
<sitemap>
<loc>http://localhost.com/sitemap-blog.xml?p=4</loc>
</sitemap>

I want the sitemap on the subdomain, that is blog.example.com

so I overwrote the index view on django.contrib.sitemap.views by changing the absolute_url to blog.sitemaps as follows

from django.contrib.sitemaps.views import x_robots_tag
from django.contrib.sites.shortcuts import get_current_site
from django.core import urlresolvers
from django.template.response import TemplateResponse

@x_robots_tag
def index(request, sitemaps,
          template_name='sitemap_index.xml', content_type='application/xml',
          sitemap_url_name='django.contrib.sitemaps.views.sitemap'):

    req_protocol = request.scheme
    req_site = get_current_site(request)

    sites = []
    for section, site in sitemaps.items():
        if callable(site):
            site = site()
        protocol = req_protocol if site.protocol is None else site.protocol
        sitemap_url = urlresolvers.reverse(
            sitemap_url_name, kwargs={'section': section})
        absolute_url = '%s://blog.%s%s' % (protocol, req_site.domain, sitemap_url)
        sites.append(absolute_url)
        for page in range(2, site.paginator.num_pages + 1):
            sites.append('%s?p=%s' % (absolute_url, page))

    return TemplateResponse(request, template_name, {'sitemaps': sites},
                            content_type=content_type)

So the output the subdomain index is something like this,

<sitemap>
<loc>http://blog.localhost.com/sitemap-whos.xml?p=3</loc>
</sitemap>
<sitemap>
<loc>http://blog.localhost.com/sitemap-whos.xml?p=4</loc>
</sitemap>

What is the correct way to make django sitemap framework to pick up the dynamic subdomains to the sitemap url?

I use django-subdomains package

like image 402
All Іѕ Vаиітy Avatar asked Dec 01 '25 05:12

All Іѕ Vаиітy


2 Answers

Marty!

I've found a great solution for my needs:

  1. No need in django-subdomains, just use simple middleware taken from here:

    class SubdomainMiddleware:
    """ Make the subdomain publicly available to classes """
    
        def process_request(self, request):
            domain_parts = request.get_host().split('.')
            if (len(domain_parts) > 2):
                subdomain = domain_parts[0]
                if (subdomain.lower() == 'www'):
                    subdomain = None
                domain = '.'.join(domain_parts[1:])
            else:
                subdomain = None
                domain = request.get_host()
    
            request.subdomain = subdomain
            request.domain = domain
    
  2. If you don't use 'sitemap index' alter sitemap view in django.contrib.sitemap.views by adding two variables req_domain and req_subdomain that are now in all requests:

find

    req_protocol = request.scheme
    req_site = get_current_site(request)

add two new lines:

    req_domain = request.domain
    req_subdomain = request.subdomain

then find

    urls.extend(site.get_urls(page=page, site=req_site,
                                  protocol=req_protocol))

and make it look like this:

    urls.extend(site.get_urls(page=page, site=req_site, r_domain=req_domain, 
                                  r_subdomain=req_subdomain, protocol=req_protocol))
  1. Now alter __init__.py in sitemap root dir:

in class Sitemap make get_urls function look like this def get_urls(self, page=1, r_domain=None, r_subdomain=None, site=None, protocol=None)

find th line domain = site.domain, comment it out and add below:

domain = r_domain
subdomain = r_subdomain

now alter this code below:

if getattr(self, 'i18n', False):
        urls = []
        current_lang_code = translation.get_language()
        for lang_code, lang_name in settings.LANGUAGES:
            translation.activate(lang_code)
            urls += self._urls(page, protocol, domain)
        translation.activate(current_lang_code)
    else:
        urls = self._urls(page, protocol, domain)

    return urls

so it looks like this:

if getattr(self, 'i18n', False):
        urls = []
        current_lang_code = translation.get_language()
        for lang_code, lang_name in settings.LANGUAGES:
            translation.activate(lang_code)
            urls += self._urls(page, protocol, domain, subdomain)
        translation.activate(current_lang_code)
    else:
        urls = self._urls(page, protocol, domain, subdomain)

    return urls
  1. find def _urls(self, page, protocol, domain) function below and make it look like this def _urls(self, page, protocol, domain, subdomain)

and in this function below find:

loc = "%s://%s%s" % (protocol, domain, self.__get('location', item))

and replace it with this:

loc = "%s://%s.%s%s" % (protocol, subdomain, domain, self.__get('location', item))
  1. profit!
like image 142
Waccess Studio Avatar answered Dec 03 '25 19:12

Waccess Studio


You can simply override _urls() method in your sitemap class and include a super call with the domain as the subdomain + host form.

class BlogSitemap(Sitemap):
    def _urls(self, page, protocol, domain):
        return super(BlogSitemap, self)._urls(
            page=page, protocol=protocol, domain='docs.djangoproject.com')
like image 36
All Іѕ Vаиітy Avatar answered Dec 03 '25 18:12

All Іѕ Vаиітy



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!