hamstap85
hamstap85

Reputation: 118

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.

Upvotes: 2

Views: 1030

Answers (2)

hamstap85
hamstap85

Reputation: 118

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

Upvotes: 1

Alasdair
Alasdair

Reputation: 308999

By the time you've patched reverse the original function may have already been imported into django.urls (where you usually import it from) and django.template.defaulttags (where the {% url %} tag uses it. Try patching it in those modules instead:

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

import django.template.defaulttags
django.template.defaulttags = patch_reverse(django.template.defaulttags)

Upvotes: 1

Related Questions