diff --git a/django/core/urlresolvers.py b/django/core/urlresolvers.py
index b634b56..2ab0235 100644
|
a
|
b
|
def get_mod_func(callback):
|
| 134 | 134 | dot = callback.rindex('.') |
| 135 | 135 | except ValueError: |
| 136 | 136 | return callback, '' |
| 137 | | return callback[:dot], callback[dot+1:] |
| | 137 | return callback[:dot], callback[dot + 1:] |
| 138 | 138 | |
| 139 | 139 | class LocaleRegexProvider(object): |
| 140 | 140 | """ |
| … |
… |
class RegexURLPattern(LocaleRegexProvider):
|
| 204 | 204 | else: |
| 205 | 205 | args = match.groups() |
| 206 | 206 | # In both cases, pass any extra_kwargs as **kwargs. |
| 207 | | kwargs.update(self.default_args) |
| | 207 | kw = self.default_args.copy() |
| | 208 | kw.update(kwargs) |
| 208 | 209 | |
| 209 | | return ResolverMatch(self.callback, args, kwargs, self.name) |
| | 210 | return ResolverMatch(self.callback, args, kw, self.name) |
| 210 | 211 | |
| 211 | 212 | @property |
| 212 | 213 | def callback(self): |
| … |
… |
class RegexURLResolver(LocaleRegexProvider):
|
| 368 | 369 | if len(args) != len(params) + len(prefix_args): |
| 369 | 370 | continue |
| 370 | 371 | unicode_args = [force_unicode(val) for val in args] |
| 371 | | candidate = (prefix_norm + result) % dict(zip(prefix_args + params, unicode_args)) |
| | 372 | candidate = (prefix_norm + result) % dict(zip(prefix_args + params, unicode_args)) |
| 372 | 373 | else: |
| 373 | 374 | if set(kwargs.keys() + defaults.keys()) != set(params + defaults.keys() + prefix_args): |
| 374 | 375 | continue |
| 375 | 376 | matches = True |
| 376 | 377 | for k, v in defaults.items(): |
| | 378 | if k in params: |
| | 379 | continue |
| 377 | 380 | if kwargs.get(k, v) != v: |
| 378 | 381 | matches = False |
| 379 | 382 | break |
diff --git a/docs/topics/http/urls.txt b/docs/topics/http/urls.txt
index f3e27ae..1a30955 100644
|
a
|
b
|
Example requests:
|
| 110 | 110 | |
| 111 | 111 | .. _Dive Into Python's explanation: http://diveintopython.net/regular_expressions/street_addresses.html#re.matching.2.3 |
| 112 | 112 | |
| | 113 | .. _named_groups: |
| | 114 | |
| 113 | 115 | Named groups |
| 114 | 116 | ============ |
| 115 | 117 | |
| … |
… |
Once you have defined namespaced URLs, you can reverse them. For details on
|
| 559 | 561 | reversing namespaced urls, see the documentation on :ref:`reversing namespaced |
| 560 | 562 | URLs <topics-http-reversing-url-namespaces>`. |
| 561 | 563 | |
| | 564 | .. _pattern_extra_options: |
| | 565 | |
| 562 | 566 | Passing extra options to view functions |
| 563 | 567 | ======================================= |
| 564 | 568 | |
| … |
… |
options to views.
|
| 587 | 591 | |
| 588 | 592 | It's possible to have a URL pattern which captures named keyword arguments, |
| 589 | 593 | and also passes arguments with the same names in its dictionary of extra |
| 590 | | arguments. When this happens, the arguments in the dictionary will be used |
| | 594 | arguments. When this happens, the arguments captured in the URL will be used |
| | 595 | instead of the arguments in the dictionary. |
| | 596 | |
| | 597 | .. versionadded:: 1.4 |
| | 598 | Previously, in case of a conflict, the arguments in the dictionary were used |
| 591 | 599 | instead of the arguments captured in the URL. |
| 592 | 600 | |
| | 601 | |
| 593 | 602 | Passing extra options to ``include()`` |
| 594 | 603 | -------------------------------------- |
| 595 | 604 | |
| … |
… |
If the URL does not resolve, the function raises an
|
| 933 | 942 | .. attribute:: ResolverMatch.kwargs |
| 934 | 943 | |
| 935 | 944 | The keyword arguments that would be passed to the view |
| 936 | | function, as parsed from the URL. |
| 937 | | |
| | 945 | function, as parsed from the URL or provided to |
| | 946 | :func:`~django.core.urlresolvers.pattern`, the keywords |
| | 947 | parsed from the URL taking precedence whenever there is |
| | 948 | a conflict. See :ref:`pattern_extra_options` and |
| | 949 | :ref:`named_groups`. |
| | 950 | |
| 938 | 951 | .. attribute:: ResolverMatch.url_name |
| 939 | 952 | |
| 940 | 953 | The name of the URL pattern that matches the URL. |
diff --git a/tests/regressiontests/i18n/patterns/tests.py b/tests/regressiontests/i18n/patterns/tests.py
index 1cc4520..5a8e868 100644
|
a
|
b
|
import os
|
| 4 | 4 | import warnings |
| 5 | 5 | |
| 6 | 6 | from django.core.exceptions import ImproperlyConfigured |
| 7 | | from django.core.urlresolvers import reverse, clear_url_caches |
| | 7 | from django.core.urlresolvers import reverse, resolve, clear_url_caches |
| 8 | 8 | from django.test import TestCase |
| 9 | 9 | from django.test.utils import override_settings |
| 10 | 10 | from django.template import Template, Context |
| … |
… |
class URLTagTests(URLTestCaseBase):
|
| 306 | 306 | {% language 'pt-br' %}{% url 'no-prefix-translated-slug' slug='apo' %}{% endlanguage %}""") |
| 307 | 307 | self.assertEqual(tpl.render(Context({})).strip().split(), |
| 308 | 308 | [u'/vertaald/apo/', u'/traduzidos/apo/']) |
| | 309 | |
| | 310 | |
| | 311 | class URLExampleTests(URLTestCaseBase): |
| | 312 | def test_demo(self): |
| | 313 | # User accesses an english url. |
| | 314 | with translation.override('en'): |
| | 315 | match = resolve('/translated/apo/') |
| | 316 | # Now we want provide links to the same page in other languages |
| | 317 | links = [] |
| | 318 | langs = ['nl', 'pt-br'] |
| | 319 | for lang in langs: |
| | 320 | with translation.override(lang): |
| | 321 | links.append(reverse(match.url_name, args=match.args, kwargs=match.match_kwargs)) |
| | 322 | self.assertEqual(links, [u'/vertaald/apo/', u'/traduzidos/apo/']) |
| | 323 | # Now we can offer the user links to the other pages |
| | 324 | # print "View the page in: ", |
| | 325 | # for lang, link in zip(langs, links): |
| | 326 | # print "<a href='%s'>%s</a> % (link, lang), |
diff --git a/tests/regressiontests/i18n/patterns/urls/default.py b/tests/regressiontests/i18n/patterns/urls/default.py
index f117502..6b94cba 100644
|
a
|
b
|
view = TemplateView.as_view(template_name='dummy.html')
|
| 9 | 9 | urlpatterns = patterns('', |
| 10 | 10 | url(r'^not-prefixed/$', view, name='not-prefixed'), |
| 11 | 11 | url(_(r'^translated/$'), view, name='no-prefix-translated'), |
| 12 | | url(_(r'^translated/(?P<slug>[\w-]+)/$'), view, name='no-prefix-translated-slug'), |
| | 12 | url(_(r'^translated/(?P<slug>[\w-]+)/$'), view, {'extra': True}, name='no-prefix-translated-slug'), |
| 13 | 13 | ) |
| 14 | 14 | |
| 15 | 15 | urlpatterns += i18n_patterns('', |
diff --git a/tests/regressiontests/urlpatterns_reverse/tests.py b/tests/regressiontests/urlpatterns_reverse/tests.py
index a1c9244..8683d60 100644
|
a
|
b
|
class ErroneousViewTests(TestCase):
|
| 511 | 511 | self.assertRaises(ViewDoesNotExist, self.client.get, '/missing_outer/') |
| 512 | 512 | self.assertRaises(ViewDoesNotExist, self.client.get, '/uncallable/') |
| 513 | 513 | |
| | 514 | class TestRereverse(TestCase): |
| | 515 | urls = 'regressiontests.urlpatterns_reverse.urls' |
| | 516 | |
| | 517 | def test_kwargs_conflict(self): |
| | 518 | match = resolve('/rereverse-overridden/12/url/') |
| | 519 | self.assertEqual(match.kwargs, {'arg': '12', 'extra': True, 'overridden': 'url'}) |
| | 520 | |
| | 521 | def test_rereverse(self): |
| | 522 | match = resolve('/rereverse/12/') |
| | 523 | self.assertEqual(reverse(match.url_name, args=match.args, kwargs=match.kwargs), '/rereverse/12/') |
| | 524 | match = resolve('/rereverse-overridden/12/url/') |
| | 525 | self.assertEqual(reverse(match.url_name, args=match.args, kwargs=match.kwargs), '/rereverse-overridden/12/url/') |
diff --git a/tests/regressiontests/urlpatterns_reverse/urls.py b/tests/regressiontests/urlpatterns_reverse/urls.py
index 1d4ae73..4a3ff6a 100644
|
a
|
b
|
urlpatterns = patterns('',
|
| 41 | 41 | url(r'^windows_path/(?P<drive_name>[A-Z]):\\(?P<path>.+)/$', empty_view, |
| 42 | 42 | name="windows"), |
| 43 | 43 | url(r'^special_chars/(.+)/$', empty_view, name="special"), |
| | 44 | url(r'^rereverse/(?P<arg>\d+)/$', empty_view, {'extra': True}, name='rereverse'), |
| | 45 | url(r'^rereverse-overridden/(?P<arg>\d+)/(?P<overridden>\w+)/$', empty_view, {'extra': True, 'overridden': 'default'}, name='rereverse-overridden'), |
| 44 | 46 | url(r'^(?P<name>.+)/\d+/$', empty_view, name="mixed"), |
| 45 | 47 | url(r'^repeats/a{1,2}/$', empty_view, name="repeats"), |
| 46 | 48 | url(r'^repeats/a{2,4}/$', empty_view, name="repeats2"), |