我有我的开发站点(localhost.com'和开发机器一样')。
此域名有两个子域名developer
和blog
。
站点地图的网址配置为,
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
包
答案 0 :(得分:4)
玛蒂!
我找到了一个很好的解决方案来满足我的需求:
不需要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
如果您未在sitemap
中使用“sitemap index”更改django.contrib.sitemap.views
视图,请添加现在的两个变量req_domain
和req_subdomain
在所有request
s:
查找
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))
__init__.py
根目录中的sitemap
: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
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 :(得分: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, '')