Issue #5 resolved

reverse() not patched on Apache/mod_wsgi

Antti Kaihola
created an issue

One of my templates displays links generated with the {{{reverse()}}} function. On {{{manage.py runserver}}} the links have a locale prefix, but on an Apache/mod_wsgi production server the prefix is missing.

Other features of localeurl work correctly: non-prefixed pages are redirected and the active language is set according to the prefix of the request path.

When running {{{manage.py shell}}} with production settings, the {{{reverse()}}} function is patched ({{{reverse.func_code}}} shows a source file path in the localeurl package), and it returns correctly prefixed URLs.

My current work-around is to {{{from localeurl.models import reverse}}} instead of {{{from django.core.urlresolvers import reverse}}}.

Comments (16)

  1. Carl Meyer repo owner

    Yes, this is a side-effect of how the monkeypatching is done, see issue 16 on the old Google Code tracker: http://code.google.com/p/django-localeurl/issues/detail?id=16 . The other workaround is to make sure you do

    from django.core import urlresolvers
    ...
    urlresolvers.reverse(...)
    

    instead of importing just the single function. Or doing the import inside a function rather than at module-level might help.

    The real solution here is to figure out some way to avoid monkeypatching at all.

  2. Carl Meyer repo owner

    My previous comment wasn't quite right; it's true that there can be a variety of reasons for the monkeypatching to not work, but in this case the problem is quite likely just that localeurl's models.py (where the monkeypatching happens) is not imported soon enough. The Django runserver performs model validation and thus imports all apps' models.py at startup, but the same does not happen under production setups (I consider this a bug in Django, to be honest).

    This suggests that one possible fix (short of figuring out a way to avoid monkeypatching) might be to import localeurl.models from some place that will get imported early on; for instance, middleware.py (since any use of django-localeurl requires installation of the middleware, and middleware gets loaded before the first request is served).

  3. Antti Kaihola reporter

    Graham Dumpleton's blog post "An improved WSGI script for use with Django" does a great job of explaining the annoying differences between manage.py runserver and mod_wsgi.

    He also proposes a mod_wsgi script which mimics how manage.py runserver works. I don't necessarily agree with that "solution", but it would probably have fixed the problem I originally described in this issue.

  4. jefurii

    I had a very similar problem in which reverse URLs worked everywhere except in get_absolute_url() functions.

    Adding from localeurl.models import reverse in middleware.py fixed this for me too.

  5. Anonymous

    Just wanted to chime in and say I had the same problem as jefurii, moving a gunicorn served site from a mac server to a linux server made all localized get_absolute_url() links loose their language prefix. His fix solved it for me too.

    Now I just have to find out why locale isn't returning localized currency values...

  6. Anonymous

    Hi guys,

    Does anyone have a definitive solution for this or is this still and issue? I have managed to replicate the issue on Apache/mod_wsgi when using get_absolute_url() method but never when using the {% url %} template tags. Due to this I avoid using the get_absolute_url method (suits me, I'm not a massive fan of it anyway)

    However I do use the `reverse()` method a lot in my views and wondered if there has been any progress to ensure that the monkeypatched version of reverse is imported early enough to always be executed?

    I am the author of django-mothertongue which uses django-localeurl 1.4+ as a pre-requisite and need to know so that I can update my documentation and inform users of my plugin that it is a known issue and to see this thread :-)

    Cheers,

    Rob

  7. andrey_shipilov

    Webfaction hosting. Same issue — reverse() not working when NOT in Debug mode. Django 1.2.4.

    Adding from localeurl.models import reverse in middleware.py worked for me too.

    By the way, there's another my project on Webfaction. Almost same set-up: Django 1.2.1 — the localeurl works perfect though...

  8. Anonymous

    In what middleware.py did you add from localeurl.models import reverse?

    Strange behavior for me too, it works in debug mode with a Django 1.2.5 and in production (gunicorn based).

    Any advice? Any alternative?

  9. Flo Ledermann
    • changed status to open

    I am still seeing this in 1.5, which has been cut long after the commit with the supposed fix.

    As mentioned in #19, the workaround is to put

    from localeurl.models import patch_reverse
    patch_reverse()
    

    on top of your urls.py.

    I am suggesting this issue should be reopenend or clarified.

  10. Roger Hunwicks

    I ran into this writing unit tests that use the Django test client and reverse(). Even adding it to the top of urls.py didn't make it run early enough, so I needed to add it to the init.py in the main project directory.

    As someone pointed out above, there was a fix in middleware.py but it was removed with no explanation.

  11. Carl Meyer repo owner

    Reintroduced the import of models in middleware in https://bitbucket.org/carljm/django-localeurl/commits/f1baca86d819348f311f7400a6ae44c2886d766f - sorry all. I missed its removal in a PR I merged just before the release of 1.5, so this issue was reintroduced in every release since then. I'll make another release shortly with the fix.

    As a side-note, I no longer use django-localeurl, so if anyone who is an active user is interested in taking over maintenance, please contact me to discuss. (I'm also curious what features in django-localeurl are causing people to still use it, even though Django has now had i18n_patterns for several releases.)

  12. Log in to comment