Search code examples
djangonamespacesdjango-urlsdjango-cms

Resolving URL based on Requesting Namespace


I am building a website using DjangoCMS that has about 10 instances of the same app. These different instances will just be used to serve different files on different pages.

Everything is working except when I go to a different instance of the application and go to the detail view it reverts back to the original application's URL and namespace.

For example, going to /university/term-syncc/ and clicking on an item in the list view redirects me to /marketing/4/ or whatever the ID is of that item.

If I go to /university/term-syncc/4/it works but I cannot get that URL to resolve automatically. I know it has something to do with my get_absolute_url calling the assets namespace but how can I force it to check the current app namespace and then run a reverse from there?

models.py

def get_absolute_url(self):
    return reverse("assets:asset_detail", kwargs={"id": self.id})

HTML

<li>
    <a href="{{obj.get_absolute_url}}">{{ obj.name }} test</a>
</li>

urls.py

url(r'^$', asset_list_view, name="asset_list"),
url(r'^(?P<id>\d+)/$', asset_detail_view, name='asset_detail'),

Solution

  • The best solution to this is to provide a configuration model for your application. Then it can use that config per instance.

    pip install aldryn-apphooks-config
    

    First off, the docs are here; http://docs.django-cms.org/en/latest/how_to/namespaced_apphooks.html#aldryn-apphooks-config

    By implementing this solution your method becomes something like this;

    class Asset(models.Model):
    
        app_config = AppHookConfigField(
            AssetConfig,
            verbose_name=_('Config'),
            help_text='',
        )
    
        def get_absolute_url(self):
            """Returns the url for this object."""
            if self.app_config and self.app_config.namespace:
                namespace = '{0}:'.format(self.app_config.namespace)
            else:
                namespace = ''
    
            return reverse(
                '{0}assets:asset_detail'.format(namespace),
                kwargs={"id": self.id}
            )
    

    Without installing this app, you can still namespace your app hooks, with that Application instance name field on the page advanced settings. You could use this instead, but it'd need args/kwargs passing around.

    In your view or templates, you could do request.current_page.application_namespace to get the namespace from the page so you could use that for your links.