diff --git a/django/core/urlresolvers.py b/django/core/urlresolvers.py index 000a56a726..1a56f11dda 100644 --- a/django/core/urlresolvers.py +++ b/django/core/urlresolvers.py @@ -9,7 +9,7 @@ a string) and returns a tuple in this format: from django.http import Http404 from django.core.exceptions import ImproperlyConfigured, ViewDoesNotExist -from django.utils.encoding import iri_to_uri +from django.utils.encoding import iri_to_uri, force_unicode from django.utils.functional import memoize import re @@ -101,7 +101,7 @@ class MatchChecker(object): # First we need to figure out whether it's a named or unnamed group. # grouped = match_obj.group(1) - m = re.search(r'^\?P<(\w+)>(.*?)$', grouped) + m = re.search(r'^\?P<(\w+)>(.*?)$', grouped, re.UNICODE) if m: # If this was a named group... # m.group(1) is the name of the group # m.group(2) is the regex. @@ -127,9 +127,9 @@ class MatchChecker(object): test_regex = grouped # Note we're using re.match here on purpose because the start of # to string needs to match. - if not re.match(test_regex + '$', str(value)): # TODO: Unicode? + if not re.match(test_regex + '$', force_unicode(value), re.UNICODE): raise NoReverseMatch("Value %r didn't match regular expression %r" % (value, test_regex)) - return str(value) # TODO: Unicode? + return force_unicode(value) class RegexURLPattern(object): def __init__(self, regex, callback, default_args=None, name=None): @@ -137,7 +137,7 @@ class RegexURLPattern(object): # callback is either a string like 'foo.views.news.stories.story_detail' # which represents the path to a module and a view function name, or a # callable object (view). - self.regex = re.compile(regex) + self.regex = re.compile(regex, re.UNICODE) if callable(callback): self._callback = callback else: @@ -201,7 +201,7 @@ class RegexURLResolver(object): def __init__(self, regex, urlconf_name, default_kwargs=None): # regex is a string representing a regular expression. # urlconf_name is a string representing the module containing urlconfs. - self.regex = re.compile(regex) + self.regex = re.compile(regex, re.UNICODE) self.urlconf_name = urlconf_name self.callback = None self.default_kwargs = default_kwargs or {} diff --git a/django/template/__init__.py b/django/template/__init__.py index b58e9f049c..6880fd5997 100644 --- a/django/template/__init__.py +++ b/django/template/__init__.py @@ -512,7 +512,7 @@ filter_raw_string = r""" )? )""" % { 'str': r"""[^"\\]*(?:\\.[^"\\]*)*""", - 'var_chars': "A-Za-z0-9\_\." , + 'var_chars': "\w\." , 'filter_sep': re.escape(FILTER_SEPARATOR), 'arg_sep': re.escape(FILTER_ARGUMENT_SEPARATOR), 'i18n_open' : re.escape("_("), @@ -520,7 +520,7 @@ filter_raw_string = r""" } filter_raw_string = filter_raw_string.replace("\n", "").replace(" ", "") -filter_re = re.compile(filter_raw_string) +filter_re = re.compile(filter_raw_string, re.UNICODE) class FilterExpression(object): """ diff --git a/tests/regressiontests/templates/tests.py b/tests/regressiontests/templates/tests.py index 5b4ff10bdb..143d1ddaa4 100644 --- a/tests/regressiontests/templates/tests.py +++ b/tests/regressiontests/templates/tests.py @@ -735,7 +735,8 @@ class Templates(unittest.TestCase): 'url02' : ('{% url regressiontests.templates.views.client_action client.id, action="update" %}', {'client': {'id': 1}}, '/url_tag/client/1/update/'), 'url03' : ('{% url regressiontests.templates.views.index %}', {}, '/url_tag/'), 'url04' : ('{% url named.client client.id %}', {'client': {'id': 1}}, '/url_tag/named-client/1/'), - 'url05' : (u'{% url метка_оператора 1 %}', {}, '/url_tag/unicode/1/'), + 'url05' : (u'{% url метка_оператора v %}', {'v': u'Ω'}, + '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'), # Failures 'url-fail01' : ('{% url %}', {}, template.TemplateSyntaxError), diff --git a/tests/regressiontests/templates/urls.py b/tests/regressiontests/templates/urls.py index 4ac9eb29f7..d79f38e0a7 100644 --- a/tests/regressiontests/templates/urls.py +++ b/tests/regressiontests/templates/urls.py @@ -9,5 +9,7 @@ urlpatterns = patterns('', (r'^client/(\d+)/$', views.client), (r'^client/(\d+)/(?P[^/]+)/$', views.client_action), url(r'^named-client/(\d+)/$', views.client, name="named.client"), - url(r'^unicode/(\d+)/$', views.client, name=u"метка_оператора"), + + # Unicode strings are permitted everywhere. + url(ur'^Юникод/(\w+)/$', views.client, name=u"метка_оператора"), )