Search code examples
pythondjangomonkeypatching

Is it possible to monkey patch Django's reverse?


Some of our urls include #. These are used for reverse lookup, both using reverse and the {% url template tag (which uses reverse internally). Django 1.8 used to leave it alone, 1.11 now encodes it to %23.

Is it possible to put a monkey patch wrapper somewhere and have it be used everywhere without fail? Here's the wrapper I have:

def patch_reverse(func):
    def inner(*args, **kwargs):
        print "inner reverse"
        url = func(*args, **kwargs)
        return url.replace("%23", "#")

    return inner


from django.urls import base
base.reverse = patch_reverse(base.reverse)

The print statement is so I can see if it's actually running.

I've tried putting it in settings, the __init__ of the first installed app, and in the urls of the first installed app. Nothing works.


Solution

  • This works. In your settings.py or equivalent settings module:

    from django import urls
    from django.core import urlresolvers
    
    _django_reverse = urlresolvers.reverse
    
    
    def _reverse(*args, **kwargs):
        result = _django_reverse(*args, **kwargs)
        # Do whatever you want to do to reverse here
        return result.replace("%23", "#")
    
    
    urlresolvers.reverse = _reverse
    urls.reverse = _reverse