summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThibault Delavallée <tde@odoo.com>2017-05-19 12:51:48 +0200
committerThibault Delavallée <tde@odoo.com>2017-08-08 14:23:58 +0200
commit014b5c9f7c2f0a5c9741569525364ff9cd6cb4cc (patch)
tree20defe1809c23177e60c5da655c3a0d959e73cb0
parentda8d418ff08aa55c7378887c9a5a06a5d12b72c0 (diff)
[MOV] website, http_routing: move (un)slug support to http_routing
Slug and unslug API is now available in http_routing. Indeed there is no link to any website or any reason to not support slufigied URLs when website is not installed. A new unslug_url method is added as a tool coming from an embedded method from website. Doing it allows to have all slug related methods defined at the same point. Support of slug and unslug in qweb rendering is also moved directly in http_routing version of ir_ui_view instead of website inheritance. This is done in order to keep things coherent. Some code from website about ModelConverter is also moved. Indeed both versions of ir_http uses some kind of placeholder to store the uid when converting urls to python. This commit unifies it by using the website one directly in base to simplify the override. This commit also updates all module importing slug. Enterprise modules will have to be updated, see related commit.
-rw-r--r--addons/http_routing/models/__init__.py3
-rw-r--r--addons/http_routing/models/ir_http.py104
-rw-r--r--addons/http_routing/models/ir_ui_view.py16
-rw-r--r--addons/mail/models/mail_thread.py2
-rw-r--r--addons/survey/models/survey.py3
-rw-r--r--addons/survey/tests/test_survey.py3
-rw-r--r--addons/website/controllers/main.py2
-rw-r--r--addons/website/models/ir_http.py38
-rw-r--r--addons/website/models/ir_ui_view.py12
-rw-r--r--addons/website/models/website.py71
-rw-r--r--addons/website/tests/test_converter.py2
-rw-r--r--addons/website_blog/controllers/main.py2
-rw-r--r--addons/website_blog/models/website_blog.py2
-rw-r--r--addons/website_crm_partner_assign/controllers/main.py2
-rw-r--r--addons/website_crm_partner_assign/models/res_partner.py2
-rw-r--r--addons/website_customer/controllers/main.py2
-rw-r--r--addons/website_event/controllers/main.py2
-rw-r--r--addons/website_event/models/event.py4
-rw-r--r--addons/website_event_track/models/event.py2
-rw-r--r--addons/website_event_track/models/event_track.py2
-rw-r--r--addons/website_forum/controllers/main.py2
-rw-r--r--addons/website_hr_recruitment/controllers/main.py2
-rw-r--r--addons/website_hr_recruitment/models/hr_recruitment.py1
-rw-r--r--addons/website_livechat/models/im_livechat.py2
-rw-r--r--addons/website_mail_channel/controllers/main.py3
-rw-r--r--addons/website_mail_channel/models/mail_channel.py2
-rw-r--r--addons/website_mail_channel/models/mail_mail.py2
-rw-r--r--addons/website_membership/controllers/main.py2
-rw-r--r--addons/website_partner/controllers/main.py2
-rw-r--r--addons/website_partner/models/res_partner.py2
-rw-r--r--addons/website_project/models/project.py1
-rw-r--r--addons/website_sale/controllers/main.py2
-rw-r--r--addons/website_slides/models/slides.py2
-rw-r--r--odoo/addons/base/ir/ir_http.py21
34 files changed, 171 insertions, 151 deletions
diff --git a/addons/http_routing/models/__init__.py b/addons/http_routing/models/__init__.py
index 67dee8c60db..c13771d0d78 100644
--- a/addons/http_routing/models/__init__.py
+++ b/addons/http_routing/models/__init__.py
@@ -1,2 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from . import ir_http
+from . import ir_ui_view
diff --git a/addons/http_routing/models/ir_http.py b/addons/http_routing/models/ir_http.py
new file mode 100644
index 00000000000..c444d7c95ff
--- /dev/null
+++ b/addons/http_routing/models/ir_http.py
@@ -0,0 +1,104 @@
+# -*- coding: utf-8 -*-
+
+import re
+import unicodedata
+
+# optional python-slugify import (https://github.com/un33k/python-slugify)
+try:
+ import slugify as slugify_lib
+except ImportError:
+ slugify_lib = None
+
+from odoo import api, models
+from odoo.addons.base.ir.ir_http import RequestUID, ModelConverter
+from odoo.http import request
+from odoo.tools import ustr
+
+
+# ------------------------------------------------------------
+# Slug API
+# ------------------------------------------------------------
+
+def slugify(s, max_length=None):
+ """ Transform a string to a slug that can be used in a url path.
+ This method will first try to do the job with python-slugify if present.
+ Otherwise it will process string by stripping leading and ending spaces,
+ converting unicode chars to ascii, lowering all chars and replacing spaces
+ and underscore with hyphen "-".
+ :param s: str
+ :param max_length: int
+ :rtype: str
+ """
+ s = ustr(s)
+ if slugify_lib:
+ # There are 2 different libraries only python-slugify is supported
+ try:
+ return slugify_lib.slugify(s, max_length=max_length)
+ except TypeError:
+ pass
+ uni = unicodedata.normalize('NFKD', s).encode('ascii', 'ignore').decode('ascii')
+ slug_str = re.sub('[\W_]', ' ', uni).strip().lower()
+ slug_str = re.sub('[-\s]+', '-', slug_str)
+
+ return slug_str[:max_length]
+
+
+def slug(value):
+ if isinstance(value, models.BaseModel):
+ if isinstance(value.id, models.NewId):
+ raise ValueError("Cannot slug non-existent record %s" % value)
+ # [(id, name)] = value.name_get()
+ identifier, name = value.id, value.display_name
+ else:
+ # assume name_search result tuple
+ identifier, name = value
+ slugname = slugify(name or '').strip().strip('-')
+ if not slugname:
+ return str(identifier)
+ return "%s-%d" % (slugname, identifier)
+
+# NOTE: as the pattern is used as it for the ModelConverter (ir_http.py), do not use any flags
+_UNSLUG_RE = re.compile(r'(?:(\w{1,2}|\w[A-Za-z0-9-_]+?\w)-)?(-?\d+)(?=$|/)')
+
+
+def unslug(s):
+ """Extract slug and id from a string.
+ Always return un 2-tuple (str|None, int|None)
+ """
+ m = _UNSLUG_RE.match(s)
+ if not m:
+ return None, None
+ return m.group(1), int(m.group(2))
+
+
+def unslug_url(s):
+ """ From /blog/my-super-blog-1" to "blog/1" """
+ parts = s.split('/')
+ if parts:
+ unslug_val = unslug(parts[-1])
+ if unslug_val[1]:
+ parts[-1] = str(unslug_val[1])
+ return '/'.join(parts)
+ return s
+
+
+class ModelConverter(ModelConverter):
+
+ def __init__(self, url_map, model=False, domain='[]'):
+ super(ModelConverter, self).__init__(url_map, model)
+ self.domain = domain
+ self.regex = _UNSLUG_RE.pattern
+
+ def to_url(self, value):
+ return slug(value)
+
+ def to_python(self, value):
+ matching = re.match(self.regex, value)
+ _uid = RequestUID(value=value, match=matching, converter=self)
+ record_id = int(matching.group(2))
+ env = api.Environment(request.cr, _uid, request.context)
+ if record_id < 0:
+ # limited support for negative IDs due to our slug pattern, assume abs() if not found
+ if not env[self.model].browse(record_id).exists():
+ record_id = abs(record_id)
+ return env[self.model].browse(record_id)
diff --git a/addons/http_routing/models/ir_ui_view.py b/addons/http_routing/models/ir_ui_view.py
new file mode 100644
index 00000000000..549f75e2f73
--- /dev/null
+++ b/addons/http_routing/models/ir_ui_view.py
@@ -0,0 +1,16 @@
+# -*- coding: ascii -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from odoo import api, models
+from odoo.addons.http_routing.models.ir_http import slug, unslug_url
+
+
+class IrUiView(models.Model):
+ _inherit = ["ir.ui.view"]
+
+ @api.model
+ def _prepare_qcontext(self):
+ qcontext = super(IrUiView, self)._prepare_qcontext()
+ qcontext['slug'] = slug
+ qcontext['unslug_url'] = unslug_url
+ return qcontext
diff --git a/addons/mail/models/mail_thread.py b/addons/mail/models/mail_thread.py
index 555a23be2cf..044f1f66d26 100644
--- a/addons/mail/models/mail_thread.py
+++ b/addons/mail/models/mail_thread.py
@@ -1914,7 +1914,7 @@ class MailThread(models.AbstractModel):
handle ir ui views. """
values = kwargs.pop('values', None) or dict()
try:
- from odoo.addons.website.models.website import slug
+ from odoo.addons.http_routing.models.ir_http import slug
values['slug'] = slug
except ImportError:
values['slug'] = lambda self: self.id
diff --git a/addons/survey/models/survey.py b/addons/survey/models/survey.py
index 84692c63f9d..c440c67862d 100644
--- a/addons/survey/models/survey.py
+++ b/addons/survey/models/survey.py
@@ -11,10 +11,9 @@ from itertools import product
from werkzeug import urls
from odoo import api, fields, models, tools, SUPERUSER_ID, _
+from odoo.addons.http_routing.models.ir_http import slug
from odoo.exceptions import UserError, ValidationError
-from odoo.addons.website.models.website import slug
-
from odoo.tools import pycompat
email_validator = re.compile(r"[^@]+@[^@]+\.[^@]+")
diff --git a/addons/survey/tests/test_survey.py b/addons/survey/tests/test_survey.py
index 04a65a02562..c7c4478248c 100644
--- a/addons/survey/tests/test_survey.py
+++ b/addons/survey/tests/test_survey.py
@@ -9,10 +9,9 @@ from itertools import product
from werkzeug import urls
from odoo import _
+from odoo.addons.http_routing.models.ir_http import slug
from odoo.exceptions import UserError
from odoo.tests.common import TransactionCase
-from odoo.addons.website.models.website import slug
-
from odoo.tools import pycompat
diff --git a/addons/website/controllers/main.py b/addons/website/controllers/main.py
index acc5e75a4d4..d1d75bea159 100644
--- a/addons/website/controllers/main.py
+++ b/addons/website/controllers/main.py
@@ -17,7 +17,7 @@ from odoo import http, models
from odoo import fields
from odoo.http import request
-from odoo.addons.website.models.website import slug
+from odoo.addons.http_routing.models.ir_http import slug
from odoo.addons.web.controllers.main import WebClient, Binary, Home
from odoo.tools import pycompat, OrderedSet
diff --git a/addons/website/models/ir_http.py b/addons/website/models/ir_http.py
index 15e751e2b09..870ec4952bc 100644
--- a/addons/website/models/ir_http.py
+++ b/addons/website/models/ir_http.py
@@ -3,7 +3,6 @@
import logging
import os
-import re
import traceback
import werkzeug
@@ -14,12 +13,12 @@ import odoo
from odoo import api, models
from odoo import SUPERUSER_ID
from odoo.http import request
-from odoo.tools import config, pycompat
+from odoo.tools import config
from odoo.exceptions import QWebException
from odoo.tools.safe_eval import safe_eval
-from odoo.addons.base import ir
-from odoo.addons.website.models.website import slug, url_for, _UNSLUG_RE
+from odoo.addons.http_routing.models.ir_http import ModelConverter
+from odoo.addons.website.models.website import url_for
logger = logging.getLogger(__name__)
@@ -29,11 +28,6 @@ logger = logging.getLogger(__name__)
odoo._geoip_resolver = None
-class RequestUID(object):
- def __init__(self, **kw):
- self.__dict__.update(kw)
-
-
class Http(models.AbstractModel):
_inherit = 'ir.http'
@@ -242,11 +236,6 @@ class Http(models.AbstractModel):
def _postprocess_args(cls, arguments, rule):
super(Http, cls)._postprocess_args(arguments, rule)
- for key, val in pycompat.items(arguments):
- # Replace uid placeholder by the current request.uid
- if isinstance(val, models.BaseModel) and isinstance(val._uid, RequestUID):
- arguments[key] = val.sudo(request.uid)
-
try:
_, path = rule.build(arguments)
assert path is not None
@@ -341,26 +330,7 @@ class Http(models.AbstractModel):
return super(Http, cls).binary_content(xmlid=xmlid, model=model, id=id, field=field, unique=unique, filename=filename, filename_field=filename_field, download=download, mimetype=mimetype, default_mimetype=default_mimetype, env=env)
-class ModelConverter(ir.ir_http.ModelConverter):
-
- def __init__(self, url_map, model=False, domain='[]'):
- super(ModelConverter, self).__init__(url_map, model)
- self.domain = domain
- self.regex = _UNSLUG_RE.pattern
-
- def to_url(self, value):
- return slug(value)
-
- def to_python(self, value):
- matching = re.match(self.regex, value)
- _uid = RequestUID(value=value, match=matching, converter=self)
- record_id = int(matching.group(2))
- env = api.Environment(request.cr, _uid, request.context)
- if record_id < 0:
- # limited support for negative IDs due to our slug pattern, assume abs() if not found
- if not env[self.model].browse(record_id).exists():
- record_id = abs(record_id)
- return env[self.model].browse(record_id)
+class ModelConverter(ModelConverter):
def generate(self, uid, query=None, args=None):
Model = request.env[self.model].sudo(uid)
diff --git a/addons/website/models/ir_ui_view.py b/addons/website/models/ir_ui_view.py
index 034ace846c2..be56b6b806b 100644
--- a/addons/website/models/ir_ui_view.py
+++ b/addons/website/models/ir_ui_view.py
@@ -3,7 +3,6 @@
import logging
from itertools import groupby
-from lxml import etree
from odoo import api, fields, models
from odoo import tools
@@ -117,21 +116,10 @@ class View(models.Model):
if 'main_object' not in qcontext:
qcontext['main_object'] = self
- def unslug_url(s):
- parts = s.split('/')
- if parts:
- unslug_val = website.unslug(parts[-1])
- if unslug_val[1]:
- parts[-1] = str(unslug_val[1])
- return '/'.join(parts)
- return s
-
qcontext.update(dict(
self._context.copy(),
website=request.website,
url_for=website.url_for,
- slug=website.slug,
- unslug_url=unslug_url,
res_company=request.website.company_id.sudo(),
default_lang_code=request.website.default_lang_code,
languages=request.website.get_languages(),
diff --git a/addons/website/models/website.py b/addons/website/models/website.py
index 0b407e4d753..ba653a7a796 100644
--- a/addons/website/models/website.py
+++ b/addons/website/models/website.py
@@ -4,22 +4,15 @@
import inspect
import logging
import math
-import unicodedata
-import re
import hashlib
+import re
from werkzeug import urls
from werkzeug.exceptions import NotFound
-# optional python-slugify import (https://github.com/un33k/python-slugify)
-try:
- import slugify as slugify_lib
-except ImportError:
- slugify_lib = None
-
-from odoo import api, fields, models
-from odoo import tools
-from odoo.tools import ustr, pycompat
+from odoo import api, fields, models, tools
+from odoo.addons.http_routing.models.ir_http import slugify
+from odoo.tools import pycompat
from odoo.http import request
from odoo.tools.translate import _
@@ -91,62 +84,6 @@ def is_multilang_url(local_url, langs=None):
return False
-####################################################
-# Slug API
-####################################################
-
-def slugify(s, max_length=None):
- """ Transform a string to a slug that can be used in a url path.
- This method will first try to do the job with python-slugify if present.
- Otherwise it will process string by stripping leading and ending spaces,
- converting unicode chars to ascii, lowering all chars and replacing spaces
- and underscore with hyphen "-".
- :param s: str
- :param max_length: int
- :rtype: str
- """
- s = ustr(s)
- if slugify_lib:
- # There are 2 different libraries only python-slugify is supported
- try:
- return slugify_lib.slugify(s, max_length=max_length)
- except TypeError:
- pass
- uni = unicodedata.normalize('NFKD', s).encode('ascii', 'ignore').decode('ascii')
- slug_str = re.sub('[\W_]', ' ', uni).strip().lower()
- slug_str = re.sub('[-\s]+', '-', slug_str)
-
- return slug_str[:max_length]
-
-
-def slug(value):
- if isinstance(value, models.BaseModel):
- if isinstance(value.id, models.NewId):
- raise ValueError("Cannot slug non-existent record %s" % value)
- # [(id, name)] = value.name_get()
- identifier, name = value.id, value.display_name
- else:
- # assume name_search result tuple
- identifier, name = value
- slugname = slugify(name or '').strip().strip('-')
- if not slugname:
- return str(identifier)
- return "%s-%d" % (slugname, identifier)
-
-# NOTE: as the pattern is used as it for the ModelConverter (ir_http.py), do not use any flags
-_UNSLUG_RE = re.compile(r'(?:(\w{1,2}|\w[A-Za-z0-9-_]+?\w)-)?(-?\d+)(?=$|/)')
-
-
-def unslug(s):
- """Extract slug and id from a string.
- Always return un 2-tuple (str|None, int|None)
- """
- m = _UNSLUG_RE.match(s)
- if not m:
- return None, None
- return m.group(1), int(m.group(2))
-
-
class Website(models.Model):
_name = "website" # Avoid website.website convention for conciseness (for new api). Got a special authorization from xmo and rco
diff --git a/addons/website/tests/test_converter.py b/addons/website/tests/test_converter.py
index 9267826c689..e5047971fa9 100644
--- a/addons/website/tests/test_converter.py
+++ b/addons/website/tests/test_converter.py
@@ -2,7 +2,7 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import unittest
-from odoo.addons.website.models.website import slugify, unslug
+from odoo.addons.http_routing.models.ir_http import slugify, unslug
from odoo.tools import pycompat
diff --git a/addons/website_blog/controllers/main.py b/addons/website_blog/controllers/main.py
index c400b8b792f..49ad2901ccc 100644
--- a/addons/website_blog/controllers/main.py
+++ b/addons/website_blog/controllers/main.py
@@ -9,8 +9,8 @@ import babel.dates
from collections import OrderedDict
from odoo import http, fields, _
+from odoo.addons.http_routing.models.ir_http import slug, unslug
from odoo.addons.website.controllers.main import QueryURL
-from odoo.addons.website.models.website import slug, unslug
from odoo.exceptions import UserError
from odoo.http import request
from odoo.tools import html2plaintext
diff --git a/addons/website_blog/models/website_blog.py b/addons/website_blog/models/website_blog.py
index 979ae14c5d3..f9df60422b2 100644
--- a/addons/website_blog/models/website_blog.py
+++ b/addons/website_blog/models/website_blog.py
@@ -7,7 +7,7 @@ import random
import itertools
from odoo import api, models, fields, _
-from odoo.addons.website.models.website import slug
+from odoo.addons.http_routing.models.ir_http import slug
from odoo.tools.translate import html_translate
from odoo.tools import html2plaintext
diff --git a/addons/website_crm_partner_assign/controllers/main.py b/addons/website_crm_partner_assign/controllers/main.py
index 3c18c7cf470..9eb27180be9 100644
--- a/addons/website_crm_partner_assign/controllers/main.py
+++ b/addons/website_crm_partner_assign/controllers/main.py
@@ -10,7 +10,7 @@ from werkzeug.exceptions import NotFound
from odoo import fields
from odoo import http
from odoo.http import request
-from odoo.addons.website.models.website import slug, unslug
+from odoo.addons.http_routing.models.ir_http import slug, unslug
from odoo.addons.website_partner.controllers.main import WebsitePartnerPage
from odoo.tools import pycompat
diff --git a/addons/website_crm_partner_assign/models/res_partner.py b/addons/website_crm_partner_assign/models/res_partner.py
index 40babddea73..aa0d40af98e 100644
--- a/addons/website_crm_partner_assign/models/res_partner.py
+++ b/addons/website_crm_partner_assign/models/res_partner.py
@@ -2,7 +2,7 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models
-from odoo.addons.website.models.website import slug
+from odoo.addons.http_routing.models.ir_http import slug
class ResPartnerGrade(models.Model):
diff --git a/addons/website_customer/controllers/main.py b/addons/website_customer/controllers/main.py
index e7318a64abf..480bb62c4d4 100644
--- a/addons/website_customer/controllers/main.py
+++ b/addons/website_customer/controllers/main.py
@@ -4,7 +4,7 @@
import werkzeug.urls
from odoo import http
-from odoo.addons.website.models.website import unslug
+from odoo.addons.http_routing.models.ir_http import unslug
from odoo.tools.translate import _
from odoo.http import request
diff --git a/addons/website_event/controllers/main.py b/addons/website_event/controllers/main.py
index 00e51627c0c..c9fc377161f 100644
--- a/addons/website_event/controllers/main.py
+++ b/addons/website_event/controllers/main.py
@@ -7,7 +7,7 @@ from datetime import datetime, timedelta
from dateutil.relativedelta import relativedelta
from odoo import fields, http, _
-from odoo.addons.website.models.website import slug
+from odoo.addons.http_routing.models.ir_http import slug
from odoo.http import request
from odoo.tools import pycompat
diff --git a/addons/website_event/models/event.py b/addons/website_event/models/event.py
index 81ec8c79629..a5e70798b8c 100644
--- a/addons/website_event/models/event.py
+++ b/addons/website_event/models/event.py
@@ -1,9 +1,7 @@
# -*- coding: utf-8 -*-
-import re
-
from odoo import api, fields, models, _
-from odoo.addons.website.models.website import slug
+from odoo.addons.http_routing.models.ir_http import slug
class EventType(models.Model):
diff --git a/addons/website_event_track/models/event.py b/addons/website_event_track/models/event.py
index baae681bc7b..92a096e42c1 100644
--- a/addons/website_event_track/models/event.py
+++ b/addons/website_event_track/models/event.py
@@ -2,7 +2,7 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models, _
-from odoo.addons.website.models.website import slug
+from odoo.addons.http_routing.models.ir_http import slug
class EventType(models.Model):
diff --git a/addons/website_event_track/models/event_track.py b/addons/website_event_track/models/event_track.py
index 5137fb0671f..6d3bf123ed0 100644
--- a/addons/website_event_track/models/event_track.py
+++ b/addons/website_event_track/models/event_track.py
@@ -3,7 +3,7 @@
from odoo import api, fields, models
from odoo.tools.translate import _, html_translate
-from odoo.addons.website.models.website import slug
+from odoo.addons.http_routing.models.ir_http import slug
class TrackTag(models.Model):
diff --git a/addons/website_forum/controllers/main.py b/addons/website_forum/controllers/main.py
index 703cf517374..6ee21087d80 100644
--- a/addons/website_forum/controllers/main.py
+++ b/addons/website_forum/controllers/main.py
@@ -11,8 +11,8 @@ import werkzeug.wrappers
from datetime import datetime
from odoo import http, modules, SUPERUSER_ID, tools, _
+from odoo.addons.http_routing.models.ir_http import slug
from odoo.addons.web.controllers.main import binary_content
-from odoo.addons.website.models.website import slug
from odoo.http import request
diff --git a/addons/website_hr_recruitment/controllers/main.py b/addons/website_hr_recruitment/controllers/main.py
index 2ed3eafc2f6..e1faf43fdc7 100644
--- a/addons/website_hr_recruitment/controllers/main.py
+++ b/addons/website_hr_recruitment/controllers/main.py
@@ -2,7 +2,7 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import http, _
-from odoo.addons.website.models.website import slug
+from odoo.addons.http_routing.models.ir_http import slug
from odoo.http import request
diff --git a/addons/website_hr_recruitment/models/hr_recruitment.py b/addons/website_hr_recruitment/models/hr_recruitment.py
index 7810ae2fccd..7d6e88c31c8 100644
--- a/addons/website_hr_recruitment/models/hr_recruitment.py
+++ b/addons/website_hr_recruitment/models/hr_recruitment.py
@@ -4,7 +4,6 @@
from werkzeug import urls
from odoo import api, fields, models
-from odoo.addons.website.models.website import slug
from odoo.tools.translate import html_translate
diff --git a/addons/website_livechat/models/im_livechat.py b/addons/website_livechat/models/im_livechat.py
index 17ad3f89a12..6dc57e0845b 100644
--- a/addons/website_livechat/models/im_livechat.py
+++ b/addons/website_livechat/models/im_livechat.py
@@ -2,7 +2,7 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, models, fields
-from odoo.addons.website.models.website import slug
+from odoo.addons.http_routing.models.ir_http import slug
from odoo.tools.translate import html_translate
diff --git a/addons/website_mail_channel/controllers/main.py b/addons/website_mail_channel/controllers/main.py
index c9b3deb268e..e14f355f9f4 100644
--- a/addons/website_mail_channel/controllers/main.py
+++ b/addons/website_mail_channel/controllers/main.py
@@ -8,7 +8,8 @@ from dateutil import relativedelta
from odoo import http, fields, tools
from odoo.http import request
-from odoo.addons.website.models.website import slug
+from odoo.addons.http_routing.models.ir_http import slug
+
class MailGroup(http.Controller):
_thread_per_page = 20
diff --git a/addons/website_mail_channel/models/mail_channel.py b/addons/website_mail_channel/models/mail_channel.py
index 519dfe7afc6..c8ef8f3414c 100644
--- a/addons/website_mail_channel/models/mail_channel.py
+++ b/addons/website_mail_channel/models/mail_channel.py
@@ -7,7 +7,7 @@ from werkzeug import urls
from odoo import api, models
from odoo.tools.safe_eval import safe_eval
-from odoo.addons.website.models.website import slug
+from odoo.addons.http_routing.models.ir_http import slug
class MailGroup(models.Model):
diff --git a/addons/website_mail_channel/models/mail_mail.py b/addons/website_mail_channel/models/mail_mail.py
index 4257c828b66..fd7d0f1fb3e 100644
--- a/addons/website_mail_channel/models/mail_mail.py
+++ b/addons/website_mail_channel/models/mail_mail.py
@@ -2,7 +2,7 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, models, tools, _
-from odoo.addons.website.models.website import slug
+from odoo.addons.http_routing.models.ir_http import slug
class MailMail(models.Model):
diff --git a/addons/website_membership/controllers/main.py b/addons/website_membership/controllers/main.py
index 3097ac0437c..42dcf599220 100644
--- a/addons/website_membership/controllers/main.py
+++ b/addons/website_membership/controllers/main.py
@@ -7,7 +7,7 @@ from odoo import fields
from odoo import http
from odoo.http import request
-from odoo.addons.website.models.website import unslug
+from odoo.addons.http_routing.models.ir_http import unslug
from odoo.tools.translate import _
diff --git a/addons/website_partner/controllers/main.py b/addons/website_partner/controllers/main.py
index 1cc4fce906f..c8cac98d969 100644
--- a/addons/website_partner/controllers/main.py
+++ b/addons/website_partner/controllers/main.py
@@ -1,8 +1,8 @@
# -*- coding: utf-8 -*-
from odoo import http
+from odoo.addons.http_routing.models.ir_http import unslug
from odoo.http import request
-from odoo.addons.website.models.website import unslug
class WebsitePartnerPage(http.Controller):
diff --git a/addons/website_partner/models/res_partner.py b/addons/website_partner/models/res_partner.py
index 2587472a026..c11922a5833 100644
--- a/addons/website_partner/models/res_partner.py
+++ b/addons/website_partner/models/res_partner.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
from odoo import api, fields, models
-from odoo.addons.website.models.website import slug
+from odoo.addons.http_routing.models.ir_http import slug
class WebsiteResPartner(models.Model):
diff --git a/addons/website_project/models/project.py b/addons/website_project/models/project.py
index e55a1d88d67..4c91abe1b7a 100644
--- a/addons/website_project/models/project.py
+++ b/addons/website_project/models/project.py
@@ -2,7 +2,6 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, exceptions, models, fields
-from odoo.addons.website.models.website import slug
class Project(models.Model):
diff --git a/addons/website_sale/controllers/main.py b/addons/website_sale/controllers/main.py
index 17d46d1a7ba..5d0972461a1 100644
--- a/addons/website_sale/controllers/main.py
+++ b/addons/website_sale/controllers/main.py
@@ -7,7 +7,7 @@ from werkzeug.exceptions import Forbidden
from odoo import http, tools, _
from odoo.http import request
from odoo.addons.base.ir.ir_qweb.fields import nl2br
-from odoo.addons.website.models.website import slug
+from odoo.addons.http_routing.models.ir_http import slug
from odoo.addons.website.controllers.main import QueryURL
from odoo.exceptions import ValidationError
from odoo.addons.website_form.controllers.main import WebsiteForm
diff --git a/addons/website_slides/models/slides.py b/addons/website_slides/models/slides.py
index ee65b15734b..01a0fda6dc2 100644
--- a/addons/website_slides/models/slides.py
+++ b/addons/website_slides/models/slides.py
@@ -11,10 +11,10 @@ import re
from werkzeug import urls
from odoo import api, fields, models, SUPERUSER_ID, _
+from odoo.addons.http_routing.models.ir_http import slug
from odoo.tools import image, pycompat
from odoo.tools.translate import html_translate
from odoo.exceptions import Warning
-from odoo.addons.website.models.website import slug
class Channel(models.Model):
diff --git a/odoo/addons/base/ir/ir_http.py b/odoo/addons/base/ir/ir_http.py
index 0aa1abc52ca..32738298293 100644
--- a/odoo/addons/base/ir/ir_http.py
+++ b/odoo/addons/base/ir/ir_http.py
@@ -10,6 +10,7 @@ import mimetypes
import os
import re
import sys
+import unicodedata
import werkzeug
import werkzeug.exceptions
@@ -27,7 +28,10 @@ from odoo.modules.module import get_resource_path, get_module_path
_logger = logging.getLogger(__name__)
-UID_PLACEHOLDER = object()
+
+class RequestUID(object):
+ def __init__(self, **kw):
+ self.__dict__.update(kw)
class ModelConverter(werkzeug.routing.BaseConverter):
@@ -38,7 +42,8 @@ class ModelConverter(werkzeug.routing.BaseConverter):
self.regex = r'([0-9]+)'
def to_python(self, value):
- env = api.Environment(request.cr, UID_PLACEHOLDER, request.context)
+ _uid = RequestUID(value=value, converter=self)
+ env = api.Environment(request.cr, _uid, request.context)
return env[self.model].browse(int(value))
def to_url(self, value):
@@ -54,7 +59,8 @@ class ModelsConverter(werkzeug.routing.BaseConverter):
self.regex = r'([0-9,]+)'
def to_python(self, value):
- env = api.Environment(request.cr, UID_PLACEHOLDER, request.context)
+ _uid = RequestUID(value=value, converter=self)
+ env = api.Environment(request.cr, _uid, request.context)
return env[self.model].browse(int(v) for v in value.split(','))
def to_url(self, value):
@@ -203,10 +209,11 @@ class IrHttp(models.AbstractModel):
@classmethod
def _postprocess_args(cls, arguments, rule):
""" post process arg to set uid on browse records """
- for name, arg in list(pycompat.items(arguments)):
- if isinstance(arg, models.BaseModel) and arg._uid is UID_PLACEHOLDER:
- arguments[name] = arg.sudo(request.uid)
- if not arg.exists():
+ for key, val in list(pycompat.items(arguments)):
+ # Replace uid placeholder by the current request.uid
+ if isinstance(val, models.BaseModel) and isinstance(val._uid, RequestUID):
+ arguments[key] = val.sudo(request.uid)
+ if not val.exists():
return cls._handle_exception(werkzeug.exceptions.NotFound())
@classmethod