import logging import datetime import base64 import copy from odoo import http, fields, _ from odoo.http import request from odoo.addons.website.controllers.main import Website SITEMAP_CACHE_TIME = datetime.timedelta(hours=12) LOC_PER_SITEMAP = 45000 class WebsiteExtended(Website): @http.route('/sitemap.xml', type='http', auth="public", website=True, multilang=False, sitemap=False) def sitemap_xml_index(self, **kwargs): current_website = request.website Attachment = request.env['ir.attachment'].sudo() View = request.env['ir.ui.view'].sudo() mimetype = 'application/xml;charset=utf-8' content = None def create_sitemap(url, content): return Attachment.create({ 'raw': content.encode(), 'mimetype': mimetype, 'type': 'binary', 'name': url, 'url': url, }) dom = [('url', '=', '/sitemap-%d.xml' % current_website.id), ('type', '=', 'binary')] sitemap = Attachment.search(dom, limit=1) seos = request.env['seo.seo'].sudo().search([('is_indexed', '=', False)]) if sitemap and not seos: # Check if stored version is still valid create_date = fields.Datetime.from_string(sitemap.create_date) delta = datetime.datetime.now() - create_date if delta < SITEMAP_CACHE_TIME: content = base64.b64decode(sitemap.datas) if not content: # Remove all sitemaps in ir.attachments as we're going to regenerated them dom = [('type', '=', 'binary'), '|', ('url', '=like', '/sitemap-%d-%%.xml' % current_website.id), ('url', '=', '/sitemap-%d.xml' % current_website.id)] sitemaps = Attachment.search(dom) sitemaps.unlink() pages = 0 locs = request.website.with_user(request.website.user_id)._enumerate_pages() locs = list(locs) for rec in request.env['seo.seo'].sudo().search([]): # for item in enumerate(locs): # if rec.url_containing in item['loc']: # del locs[n] locs = [item for item in locs if rec.url_containing not in item['loc']] rec.is_indexed = True while True: values = { 'locs': locs, 'url_root': request.httprequest.url_root[:-1], } urls = View._render_template('website.sitemap_locs', values) if urls.strip(): content = View._render_template('website.sitemap_xml', {'content': urls}) pages += 1 last_sitemap = create_sitemap('/sitemap-%d-%d.xml' % (current_website.id, pages), content) if len(locs) * pages < LOC_PER_SITEMAP: break else: break if not pages: return request.not_found() elif pages == 1: # rename the -id-page.xml => -id.xml last_sitemap.write({ 'url': "/sitemap-%d.xml" % current_website.id, 'name': "/sitemap-%d.xml" % current_website.id, }) else: # TODO: in master/saas-15, move current_website_id in template directly pages_with_website = ["%d-%d" % (current_website.id, p) for p in range(1, pages + 1)] # Sitemaps must be split in several smaller files with a sitemap index content = View._render_template('website.sitemap_index_xml', { 'pages': pages_with_website, 'url_root': request.httprequest.url_root, }) create_sitemap('/sitemap-%d.xml' % current_website.id, content) return request.make_response(content, [('Content-Type', mimetype)])