How to write Model.get_absolute_url()?

158 views
Skip to first unread message

Jon Ribbens

unread,
Dec 5, 2015, 7:29:29 PM12/5/15
to Django users
I'm using Django 1.8. If I'm writing an app, and I want to add get_absolute_url() to a model, the question is: what do I put for the first argument to 'reverse'?

The documentation at https://docs.djangoproject.com/en/1.8/topics/http/urls/#url-namespaces implies that I need to know two things: the instance name, and the app name. The problem is that get_absolute_url() knows neither of these.

Imagine my app has a urlpattern like:

    url(r'^view/(\d+)$', views.view, name="view")

I could just say reverse("view", self.id) but what if another app has a view called 'view'? What if my app is instanced twice - i.e. as shown in the docs:

    url(r'^author-polls/', include('polls.urls', namespace='author-polls', app_name='polls')),
    url(r'^publisher-polls/', include('polls.urls', namespace='publisher-polls', app_name='polls')),

?

pa xapy

unread,
Dec 7, 2015, 5:24:48 AM12/7/15
to Django users
there is two approaches:
you can either create unique names for each url pattern entry like url(...., name='my_app_unique_view_name')
or use namespace and pass it to reverse like reverse('my-app-namespace:my-url-pattern-view-name')

Jon Ribbens

unread,
Dec 7, 2015, 5:57:41 AM12/7/15
to Django users
On Monday, 7 December 2015 10:24:48 UTC, pa xapy wrote:
there is two approaches:
you can either create unique names for each url pattern entry like url(...., name='my_app_unique_view_name')
or use namespace and pass it to reverse like reverse('my-app-namespace:my-url-pattern-view-name')

But that doesn't account for either of the points in my question, i.e. that (a) the app does not know its "app_name" as that is defined by the site not the app, and (b) if you did somehow know and use the app_name then how does Django know which instance you mean?

Caique Reinhold

unread,
Dec 7, 2015, 3:09:34 PM12/7/15
to Django users
You use the app namespace which you defined in the site for each app, not the app_name. That's what pa xapy meant.

In the example you gave it would be like: reverse('author-polls:view', self.id).

Jon Ribbens

unread,
Dec 7, 2015, 3:45:03 PM12/7/15
to Django users
On Monday, 7 December 2015 20:09:34 UTC, Caique Reinhold wrote:
You use the app namespace which you defined in the site for each app, not the app_name. That's what pa xapy meant.

In the example you gave it would be like: reverse('author-polls:view', self.id).

But (a) the app cannot know that I might make an instance of it called 'author-polls' (I might after all make an instance of it called anything at all) and (b) what if this is not the 'author-polls' instance?

Caique Reinhold

unread,
Dec 7, 2015, 4:14:45 PM12/7/15
to Django users
Well, as this is implemented you have to know your namespaces during development. But now i see what's your problem.

I'm not sure, but i don't think it is encouraged to have multiple instances of the same app in one project. I think the sites contrib app or some other method of having this author/publisher distinction within the same app would better suit your needs.

Jon Ribbens

unread,
Dec 7, 2015, 4:45:07 PM12/7/15
to Django users
On Monday, 7 December 2015 21:14:45 UTC, Caique Reinhold wrote:
Well, as this is implemented you have to know your namespaces during development. But now i see what's your problem.

I'm not sure, but i don't think it is encouraged to have multiple instances of the same app in one project. I think the sites contrib app or some other method of having this author/publisher distinction within the same app would better suit your needs.

I don't have any needs (the author/publisher thing is from the Django docs, not my app), I'm just trying to write an utterly simple app and I'm trying to find out the "best practices" way of doing it.

The impression I'm getting is that the documentation is misleading and the "instance namespace" feature does not actually really work. And that the answer to my question is that I should use an app namespace and put as part of the installation instructions for my app that the user must put app_name="foo" in their site's urls.py or the app will fail. I guess this is why one of the changes in 1.9 is that now you can define the app_name in the app rather than in the site.

knbk

unread,
Dec 7, 2015, 6:40:51 PM12/7/15
to Django users
Namespaces are a mess, and have been for a while. 1.9 cleans this up a bit. Some advice for 1.8 to stay in line with the 1.9 changes:
  • Always define an application namespace when using an instance namespace.
  • An app shouldn't depend on the project's url configuration, so always use the application namespace in the view name, i.e. reverse('polls:view'), not reverse('author-polls:view').
  • A project that uses an app may point to a specific instance namespace of that app when necessary, i.e. on the front page with links to both author-polls and publisher-polls.
  • The currently active instance namespace is available as request.resolver_match.namespace.
  • You can set request.current_app = request.resolver_match.namespace before rendering templates, and the {% url %} template tag will use the current namespace for urls in the same application namespace.
  • You can explicitly pass the current namespace to current_app in reverse() to do the same. 
The rationale behind the 1.9 changes it that an application namespace should define the name of a view, which the app must be able to know and reverse. The instance namespace defines a specific location for that view, and a project defines the exact location of that view and may even specify multiple locations. The application should typically reverse views for the currently active instance namespace, while the project may point to a specific instance namespace. By giving the app the ability to define its own application namespace, it is fully in control of its own url configuration and doesn't require any additional action from the user of the app. Since instance namespaces can no longer exist without an application namespace (well, it's deprecated anyway), it is always possible to reverse a view using the application namespace.

In 1.9, you can then just move the application namespace to the app's urlconf, and remove the request.current_app = request.resolver_match.namespace, since 1.9 does this for you. 

I hope this helps a bit. If you have any more questions feel free to ask. 

Jon Ribbens

unread,
Dec 7, 2015, 6:51:17 PM12/7/15
to Django users
On Monday, 7 December 2015 23:40:51 UTC, knbk wrote:
Namespaces are a mess, and have been for a while. 1.9 cleans this up a bit. Some advice for 1.8 to stay in line with the 1.9 changes:
  • Always define an application namespace when using an instance namespace.
  • An app shouldn't depend on the project's url configuration, so always use the application namespace in the view name, i.e. reverse('polls:view'), not reverse('author-polls:view').
  • A project that uses an app may point to a specific instance namespace of that app when necessary, i.e. on the front page with links to both author-polls and publisher-polls.
  • The currently active instance namespace is available as request.resolver_match.namespace.
  • You can set request.current_app = request.resolver_match.namespace before rendering templates, and the {% url %} template tag will use the current namespace for urls in the same application namespace.
It seems a bit weird that that's not automatic.
  • You can explicitly pass the current namespace to current_app in reverse() to do the same. 
That still leaves the question of what Model.get_absolute_url() should do, given that it has no way to get the current app that I can see. Thank you for your very helpful comments though.

knbk

unread,
Dec 7, 2015, 7:44:02 PM12/7/15
to Django users
It seems a bit weird that that's not automatic.

That's what I thought, so it's automatic in 1.9.

That still leaves the question of what Model.get_absolute_url() should do, given that it has no way to get the current app that I can see. Thank you for your very helpful comments though.

It can't know the current app. I never use it for anything but the helpful "View on site" link in the admin. I have some plans to revisit this API, but that depends on some other work I'm still finishing. 

Jon Ribbens

unread,
Dec 8, 2015, 11:27:56 AM12/8/15
to Django users
On Tuesday, 8 December 2015 00:44:02 UTC, knbk wrote:
It seems a bit weird that that's not automatic.

That's what I thought, so it's automatic in 1.9.

Ah, brilliant.
 
That still leaves the question of what Model.get_absolute_url() should do, given that it has no way to get the current app that I can see. Thank you for your very helpful comments though.

It can't know the current app. I never use it for anything but the helpful "View on site" link in the admin. I have some plans to revisit this API, but that depends on some other work I'm still finishing. 

Thanks. I think I have a vague idea what's going on now ;-) 
Reply all
Reply to author
Forward
0 new messages