ApplicationContent and app_reverse

47 views
Skip to first unread message

Martin J. Laubach

unread,
Mar 28, 2013, 4:50:34 PM3/28/13
to django-...@googlegroups.com
  I have thought a bit about the app_reverse problem when using an external django app as ApplicationContent.

  Currently, to properly support url reversion, one has to modify the external app and replace each and every django.core.urlresolver.reverse() call into feincms.content.application.models.app_reverse(), which to boot also needs an additional urlconf parameter. That is undesirable because:
  1. it tightly couples the application to the FeinCMS environment, it's currently basically impossible to reuse an app without munging it
  2. it moves knowledge about the urlconf parameter into the individual views, where it obviously does not belong
  I just committed a small change that at least allows one to curry the app_reverse like this

        from functools import partial
       from feincms.content.application.models import app_reverse

       reverse = partial(app_reverse, urlconf='some.urls')

  which helps with the first point a small bit, at least one does not need to change all the reverses individually. It should also be possible to wrap that in a try/catch block to give the app at least a chance of working outside of a FeinCMS site.

  However, you still need to inject knowledge about the urlconf into the app. The right place to get that knowledge from would obviously be the call to create_content_type:

        Page.create_content_type(ApplicationContent,
             APPLICATIONS=( ('some_urls', 'Demoapp'),)

  Any ideas how one could get rid of the verbatim urlconf in the app? Perhaps introspection of something? I'm pretty sure that urlconf is known at that point somewhere....? Ideas?

  Cheers,

    mjl

Martin J. Laubach

unread,
May 17, 2013, 6:13:16 AM5/17/13
to django-...@googlegroups.com
  Talking to oneself is a sure sign of problems, but still... for the records, here's the best I could come up with so far:

  Adding something like this to the view code:

reverse = None

def _make_reverse(request):
    global reverse
    if reverse is None:
        urlconf = request._feincms_extra_context['app_config']['urlconf_path']
        reverse = partial(app_reverse, urlconf=urlconf)

def needs_reverse(f):
    def wrapper(request, *args, **kwargs):
        _make_reverse(request)
        return f(request, *args, **kwargs)
    return wrapper

  and decorating the individual views with @needs_reverse does automatically detect the urlconf. On the other hand, it needs decorating every view that wants to reverse stuff, so it's more intrusive than just hardcoding the urlconf.

  Cheers,

    mjl

Martin J. Laubach

unread,
Aug 1, 2014, 7:05:46 AM8/1/14
to django-...@googlegroups.com
Even more disturbing is answering one's posts after a year...

Here's a small function that does everything automatically. 

from itertools import chain
from django.core.urlresolvers import reverse, NoReverseMatch
from feincms.content.application.models import app_reverse, ApplicationContent

# Note: Mutable dict as default intentional
def multiapp_reverse(name, _reverse_cache={}, **kwargs):
    retval
= None
   
for urlconf in chain((_reverse_cache.get(name, None), ),
                         
ApplicationContent.ALL_APPS_CONFIG.keys()):
       
try:
           
if urlconf is None:
                retval
= reverse(name, **kwargs)
           
else:
                retval
= app_reverse(name, urlconf=urlconf, **kwargs)
            _reverse_cache
[name] = urlconf
           
break
       
except NoReverseMatch:
           
pass
   
else:
       
raise NoReverseMatch("Cannot reverse \"%s\"" % name)

   
return retval


I'm probably overlooking the obvious -- is there a fundamental problem with something like that? It's intended as drop in replacement for reverse() for easier 3rd party app integration.

Cheers...
Reply all
Reply to author
Forward
0 new messages