#29415: custom url converters are not picked up on reverse when part of included
patterns
---------------------------------------+------------------------
               Reporter:  Xaroth       |          Owner:  nobody
                   Type:  Bug          |         Status:  new
              Component:  Core (URLs)  |        Version:  2.1
               Severity:  Normal       |       Keywords:
           Triage Stage:  Unreviewed   |      Has patch:  0
    Needs documentation:  0            |    Needs tests:  0
Patch needs improvement:  0            |  Easy pickings:  0
                  UI/UX:  0            |
---------------------------------------+------------------------
 Under normal circumstances, url converters `to_url` methods are called
 when reversing a url, however, this behavior is inconsistent when used
 with included sub-patterns

 To demonstrate:
 {{{
 from django.urls import path, include, register_converter
 from django.urls.converters import StringConverter


 class ReverseConverter(StringConverter):
     def to_python(self, value):
         """More complex use cases are possible, but this simple case of
 reversing the string already shows it in effect"""
         return value[::-1]

     def to_url(self, obj):
         """More complex use cases are possible, but this simple case of
 reversing the string already shows it in effect"""
         return obj[::-1]

 register_converter(ReverseConverter, 'rstr')


 def noop(request):  # A noop since we are merely testing reverse()
     pass


 # Patterns in here will
 included_patterns = [
     path('', noop, name='fail-case-1'),
     path('<rstr:itemb>', noop, name='fail-case-2'),
 ]

 direct_patterns = [
     path('<rstr:item>', noop, name='success-case-1'),
     path('<rstr:item>/<rstr:itemb>', noop, name='success-case-2'),
 ]

 urlpatterns = [
     path('<rstr:item>/', include(included_patterns)),
     path('', include(direct_patterns)),
     path('<rstr:item>', noop, name='success-case-3'),
 ]
 }}}

 When running the following test, both patterns -should- return the same
 URL, however, they do not:

 {{{
 In [1]: from django.urls import reverse

 In [2]: reverse('success-case-1', kwargs={'item': 'abc123'})  # Expected:
 '/321cba'
 Out[2]: '/321cba'

 In [3]: reverse('success-case-2', kwargs={'item': 'abc123', 'itemb':
 'xyz789'})  # Expected: '/321cba/987zyx'
 Out[3]: '/321cba/987zyx'

 In [4]: reverse('success-case-3', kwargs={'item': 'abc123'})  # Expected:
 '/321cba'
 Out[4]: '/321cba'

 In [5]: reverse('fail-case-1', kwargs={'item': 'abc123'})  # Expected:
 '/321cba/'
 Out[5]: '/abc123/'

 In [6]: reverse('fail-case-2', kwargs={'item': 'abc123', 'itemb':
 'xyz789'})  # Expected: '/321cba/987zyx'
 Out[6]: '/abc123/987zyx'
 }}}
 Note that at the last case, `item` is not reversed, where `itemb` is.

 The main culprit (I think) is that when populating the URLResolver's
 reverse_dict, included sub-resolvers are not updated with the converters
 of the resolver that includes them, as such, they skip the converters for
 the base resolver when reversing the URL.

 I have confirmed this inconsistency in versions 2.0 through 2.0.5, 2.1a1
 as well as master (@9f6188b).

-- 
Ticket URL: <https://code.djangoproject.com/ticket/29415>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-updates+unsubscr...@googlegroups.com.
To post to this group, send email to django-updates@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/049.b2bfc22436fe8d509a621cc0ab2eb21c%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to