Require explicit monkeypatching instead of relying on being first to load

Patryk Zawadzki avatarPatryk Zawadzki created an issue

If any of the other INSTALLED_APPS imports a model in its __init__.py file, that model (and other models coming from the same app) will be loaded before localeurl has a chance to patch resolve(). The magic breaks and some models return localized URLs for get_absolute_url() while others return the unlocalized ones.

A solution that always works is to always explicitly call:

from localeurl.models import patch_reverse
patch_reverse()

...on top of your settings.py.

However currently force-importing localeurl.models has the side effect of reloading the whole settings file twice due to a circular dependency between the two (localeurl imports settings to check USE_I18N).

This is why I propose to:

  1. move the patch_reverse to the main module level (__init__.py)
  2. drop the call to patch_reverse and possibly replace it with a warning if the function is still unpatched once the control flow reaches models.py
  3. document the need to call the patcher directly

Comments (7)

  1. Carl Meyer
    • changed status to open

    The explicit patching should happen in urls.py (or whatever ROOT_URLCONF points to), not settings.py. Importing anything in settings.py is a bad pattern. Since this is url-related, urls.py is a sensible place for it anyway.

    Otherwise, this seems like a sensible proposal.

  2. Bojan Mihelac

    I have just been bitten by similar problem. For some reason in a local development server URLs where prefixed properly, while on the production server some were and some other were not. Production is apache+modwsgi. It would be too painful to debug this in production and try to find exactly where and why the issue appear.

    Explicit patching on top of urls.py as noted above resolved this issue, so I guess it would be good idea to document it.

  3. hejsan

    I just spent half a day trying to workaround this. Silly me for not realizing this was a common error. This should definitely be mentioned in the installation docs. I fixed it by putting this at the top of my urls.py:

    from localeurl.models import patch_reverse
    patch_reverse()
    

    Thanks patrys!

  4. Log in to comment
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.