#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.