2

我有我的开发站点(localhost.com '在开发机器上')。

该域有两个子域,developer并且blog.

站点地图的 url 配置是,

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.viewsblog.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 站点地图框架获取站点地图 url 的动态子域的正确方法是什么?

我用django-subdomains

4

4 回答 4

4

马蒂!

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

  1. 不需要django-subdomains,只需使用从这里获取的简单中间件:

    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视图,这些变量现在位于所有s 中:django.contrib.sitemap.viewsreq_domainreq_subdomainrequest

寻找

    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__.pysitemap目录:

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)

并在下面的这个函数中找到:

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

并将其替换为:

loc = "%s://%s.%s%s" % (protocol, subdomain, domain, self.__get('location', item))
  1. 利润!
于 2016-11-16T18:16:49.317 回答
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, '')
于 2018-05-24T10:30:16.673 回答
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我创建的扩展站点地图的类一起使用。这个类只添加了一个子域属性并添加了两行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()

瞧!

于 2017-08-02T16:20:50.477 回答
1

您可以简单地覆盖_urls()站点地图类中的方法,并包含一个以域作为子域 + 主机形式的超级调用。

class BlogSitemap(Sitemap):
    def _urls(self, page, protocol, domain):
        return super(BlogSitemap, self)._urls(
            page=page, protocol=protocol, domain='docs.djangoproject.com')
于 2017-08-26T08:09:38.480 回答