0

Basically i am trying to use .get_absolute_url() to return dynamic links in relative to the current app running, in other words reverse the model url to a different url based on which app being called.

Let me try to explain what i am trying to do by example, We have three apps

  • Blog (serves as a shared data layer, contains models for post, authors ... etc)
  • BloggerWay (serves as a view layer number one, uses the Blog app models to display content in some given layout)
  • TumblrWay (serves as another view layer, again uses the Blog app models to display content in some given layout)

My urls.py files goes like

----------
*Project.urls.py*
----------
urlpatterns= [
  url('/blogger/', include(BloggerWay.urls.py, namespace='blogger'),
  url('/tumblr/', include(TumblrWay.urls.py, namespace='tumblr'),]
----------
*BloggerWay.urls.py*
----------
urlpatterns= [
  url('/post/(?P<id>\d+)', Blog.as_view(), name='blog'),]
----------
 *TumblrWay.urls.py*
----------
urlpatterns= [
  url('/post/(?P<id>\d+)', Blog.as_view(), name='blog'),]

My question is How can i define .get_absolute_url() method for the Post model so it knows which app we are in and return the correct url to it.

example: if in BloggerWay return '/blogger/post' if in TumblrWay return '/tumblr/post'


I know that i can use the reverse() function to get the url for a given named pattern and that it accepts a current_app= argument but my problem is how can i get the running app so i can pass it.

class Post(...):
  def get_absolute_url(self):
    WhoAmI = ... #get current app here, BUT HOW!
    return reverse('post', current_app=WhoAmI)

Solutions that i want to avoid:

  • I can inherit the Post class in both of the apps, override the .get_absolute_url() there, hardcoding the name space of each app in it. Then use the class in my app instead of directly using the one defined as model/table.(while offcourse avoid performing migrations for that class, even better define it somewhere else than models.py)

1 Answers1

0

Implement another property for get_url() for your class. The reverse function should includes "namespace:name" e.g

class Post(...):...
    def get_blogger_url(self):
        return reverse("blogger:post", kwargs={"id":self.id}) # for Blogger
    def get_tumblr_url(self):
        return reverse("tumblr:post", kwargs={"id":self.id}) # for Tumblr
gema
  • 523
  • 1
  • 7
  • 17
  • Thank you @Barack for the suggestion. It will work but i guess it won't be efficient for two reasons. _First_ when dealing with a large number of apps that utilize the same model's app, we will end up having a method for each of them. Also the developer will need to remember those methods name when using them in his template as opposed to just using the get_absolute_url() method. _Second_ hard coding the name space means that the model's app would be dependent on the name spaces the developer uses. – Mohammed Ibrahim Apr 09 '17 at 00:22
  • To continue: The developer will end up modifying the model's app, which in turn means that the app will lose its pluggable ability. – Mohammed Ibrahim Apr 09 '17 at 00:26