将子域包含到Django站点地图网址的正确方法是什么?

时间:2015-08-06 10:27:49

标签: python django sitemap subdomain django-sitemaps

我有我的开发站点(localhost.com'和开发机器一样')。

此域名有两个子域名developerblog

站点地图的网址配置为,

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}),

使用站点地图索引创建站点地图时, 站点地图创建为

<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>

我想在子域上使用站点地图,即blog.example.com

所以我通过将absolute_url更改为index来覆盖django.contrib.sitemap.views上的blog.sitemaps视图,如下所示

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)

所以子域索引的输出是这样的,

<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>

使django站点地图框架将动态子域名添加到站点地图网址的正确方法是什么?

我使用django-subdomains

4 个答案:

答案 0 :(得分:4)

玛蒂!

我找到了一个很好的解决方案来满足我的需求:

  1. 不需要django-subdomains,只需使用取自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. 如果您未在sitemap中使用“sitemap index”更改django.contrib.sitemap.views视图,请添加现在的两个变量req_domainreq_subdomain在所有request s:

  3. 查找

        req_protocol = request.scheme
        req_site = get_current_site(request)
    

    添加两行:

        req_domain = request.domain
        req_subdomain = request.subdomain
    
    然后找

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

    并使它看起来像这样:

        urls.extend(site.get_urls(page=page, site=req_site, r_domain=req_domain, 
                                      r_subdomain=req_subdomain, protocol=req_protocol))
    
    1. 现在改变__init__.py根目录中的sitemap
    2. class Sitemap使get_urls函数中的

      看起来像def get_urls(self, page=1, r_domain=None, r_subdomain=None, site=None, protocol=None)

      找到第domain = site.domain行,将其评论并添加到下面:

      domain = r_domain
      subdomain = r_subdomain
      

      现在改变以下代码:

      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
      

      所以它看起来像这样:

      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. 在下方找到def _urls(self, page, protocol, domain)功能,并使其显示为def _urls(self, page, protocol, domain, subdomain)
      2. 并在下面的函数中找到:

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

        并将其替换为:

        loc = "%s://%s.%s%s" % (protocol, subdomain, domain, self.__get('location', item))
        
        1. 的利润!

答案 1 :(得分:2)

您只需覆盖站点地图类中的_urls()方法,并将域名作为子域名+主机表单进行超级调用。

class BlogSitemap(Sitemap):
    def _urls(self, page, protocol, domain):
        return super(BlogSitemap, self)._urls(
            page=page, protocol=protocol, domain='docs.djangoproject.com')

答案 2 :(得分:1)

我的解决方案只扩展了两个类,为具有子域的站点地图创建了一组可重复使用的组件。

首先,我创建了一个新的SubdomainSite类,实现了django.contrib.sites.models.Site

的接口
from __future__ import unicode_literals

from django.utils.encoding import python_2_unicode_compatible


@python_2_unicode_compatible
class SubdomainSite(object):
    """
    SubdomainSite shares the interface of Site and adds subdomain support.
    """
    def __init__(self, subdomain, site=None):
        self.subdomain = subdomain
        self.extend_site(site)

    def __str__(self):
        return self.domain

    def extend_site(self, site):
        """Always returns the root level site extended with subdomain."""
        if issubclass(site.__class__, self.__class__):
            return self.extend_site(site.root_site)
        elif hasattr(site, 'domain'):
            self.root_site = site
        self.domain = self.name = '{0}.{1}'.format(self.subdomain, site)
        return self

    def save(self, force_insert=False, force_update=False):
        raise NotImplementedError('RequestSite cannot be saved.')

    def delete(self):
        raise NotImplementedError('RequestSite cannot be deleted.')

然后将其与我创建的类SubdomainSitemap一起使用,该类扩展了Sitemap。这个类只添加一个子域属性,并向get_urls添加两行 - 它没有看起来那么复杂,原始类只是对一个函数有点太过分了。

from django.contrib.sitemaps import Sitemap


class SubdomainSitemap(Sitemap):
    """Adds subdomain support to sitemaps"""
    subdomain = None

    def get_urls(self, page=1, site=None, protocol=None):
        """Always uses this sitemap's subdomain if supplied."""
        # Determine protocol
        if self.protocol is not None:
            protocol = self.protocol
        if protocol is None:
            protocol = 'http'

        # Determine domain
        if site is None and self.subdomain is None:
            if django_apps.is_installed('django.contrib.sites'):
                Site = django_apps.get_model('sites.Site')
                try:
                    site = Site.objects.get_current()
                except Site.DoesNotExist:
                    pass
            if site is None:
                raise ImproperlyConfigured(
                    "To use sitemaps, either enable the sites framework or pass "
                    "a Site/RequestSite object in your view."
                )
        else:
            # Setting a subdomain site overrides supplied site
            site = self.subdomain
        domain = site.domain

        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

现在将它们绑定在您的站点地图类中!

from django.contrib.sites.models import Site
from sitemaps import SubdomainSite, SubdomainSitemap
from blog.models import Post

current_site = Site.objects.get_current()


class BlogSitemap(SubdomainSitemap):
    changefreq = 'monthly'
    subdomain = SubdomainSite('blog', current_site)
    protocol = 'https'

    def items(self):
        return Post.objects.all()

瞧!

答案 3 :(得分:1)

对于All Іѕ Vаиітy答案的更一般版本,您可以将其用于您可能需要的任何子域:

class FixedSitemap(Sitemap):
    priority = 0.5
    changefreq = 'monthly'
    protocol = 'https'

    def items(self):
        # Add all your items here
        return ['docs.yourdomain.io']

    def location(self, obj):
        return obj

    def _urls(self, page, protocol, domain):
        return super(FixedSitemap, self)._urls(page, protocol, '')