template url reverse and namespacing is driving me crazy

143 views
Skip to first unread message

pjotr

unread,
Nov 30, 2014, 2:51:17 PM11/30/14
to django...@googlegroups.com
Alright, I'm already crazy, so the subject is a bit of a lie. But nevermind.

I think I like namespacing, it is really nice. But there is something not that clear in the documentation of Django, and how to make usage of namespace, in a consistent way. Lets take it by example.

I'm using this pretty amazing app "greeter" that was written by a superuser from a country far away from my own. It is a pretty simple app, that has two url mappings:

url(r'^list/$', HelloWorldList.as_view(), name='list'),
url(r'^greet/(?P<pk>\d+)/$', HelloWorldGreet.as_view(), name='greet'),

The template of HelloWorldList view is using the template tag url like this: {% url 'greet' greeter.pk %}.

After that I hook up the application in my project by including it in my project urls.py:

url(r'^greeter/', include('greeter.urls')),

Everything works well, I felt like a Django guru integrating the hello world app to my own project. I can access /greeter/list and clicking on the greetings works well.

Later that night I go to bed, feeling confident, kissing my wife goodnight with a smile on my face. I wake up warm, sweaty, with my heart beating. I run to my laptop, just realized I forgot to namespace the greet app, because I just realized I am using the list name in another place in my project, and I don't have any automated tests, so I better namespace it quickly.

So, I change my project url mapping to this:

url(r'^greeter/', include('greeter.urls', namespace='greeter')),

Boom crash. Visiting the /greeter/list/ page gives me:

Reverse for 'greet' with arguments '()' and keyword arguments '{pk:1}' not found. 0 pattern(s) tried: []

I start to doubt the author of the 'greeter' app, that he didn't prepare his app for being used in other projects, where the project might need namespacing to avoid conflicts.

Digging into Django documentation, I don't really find any argument for the author of the 'greeter' app to be sloppy and not caring of details.

Someone who can enlighten me why django doesn't try to default to the current app when resolving namespaces? Or can someone enlighten me how I can help out the author of the 'greeting' app, so it really is reusable in other projects?

Kelvin Wong

unread,
Nov 30, 2014, 10:35:53 PM11/30/14
to django...@googlegroups.com
Change all instances of this in your templates

{% url 'greet' greeter.pk %}

To this

{% url 'greeter:greet' greeter.pk %}.

Since you are now using the 'greeter' namespace. Also, the other one is 

{% url 'greeter:list' %} and not {% url 'list' %} because you are using the 'greeter' namespace.

K

pjotr

unread,
Dec 1, 2014, 8:54:02 AM12/1/14
to django...@googlegroups.com
That is not the point. I know I can do that, but that doesn't solve the issue of an reusable app. I could fork the 'greeter' project, add my namespace in the templates, and it would be all working. But still that is not the point.

The point is: how can I write a reusable app so that someone else, that uses it can namespace it into whatever namespace they want, and it should still work.

Tim Graham

unread,
Dec 1, 2014, 9:33:40 AM12/1/14
to django...@googlegroups.com
Did you read about passing 'current_app' to your template rendering calls? https://docs.djangoproject.com/en/1.7/topics/http/urls/#id4

The contrib.admin class has app_name='admin' and namespace='admin' by default, but you can create a custom AdminSite(name='foo') to customize the instance namespace. In the admin's views, calls to reverse and template rendering pass (current_app=self.admin_site.name). That should be a good example to follow in making your app reusable.

If you think the documentation could be improved, I'd happily review any patch you could submit, thanks!

Ionel Cristian Mărieș

unread,
Dec 1, 2014, 9:55:57 AM12/1/14
to django...@googlegroups.com
Tim, this is not about documentation. It's a question of whose responsibility this (setting the current_app) is. The reusable app code (where one would set the current_app) is out of pjotr's control, unless he forks it and makes a fix.

Making a fix is not that bad but the problem is that very few reusable app authors correctly handle the namespace issue. I for one can't name one reusable app that correctly sets the current_app - which leads me to believe there's something wrong in how Django handles this.

Django should have a default current_app in the RequestContext. Maybe this should be brought up on django-dev mailing list, or even a bug report.

Meanwhile this can be handled with a custom context processor (TEMPLATE_CONTEXT_PROCESSORS setting) that does something like:

  def add_namespace_processor(request):
    return {'current_app': request.resolver_match.namespace}

Ionel Cristian Mărieș

unread,
Dec 1, 2014, 10:11:09 AM12/1/14
to django...@googlegroups.com
This, this is not about improving the documentation. It's pretty clear how to solve the problem.

The issue here is whom should have the responsibility of setting the correct current_app in the template context. One can always fix 3rd party apps but it gets old after a while. I for one can't name a single reusable app that correctly sets the current_app in it's views - which leads me to believe this is a widespread issue and Django could have better defaults.

A provisory solution would be having a context processor like this:

  def add_default_namespace(request):

    return {'current_app': request.resolver_match.namespace}

On Monday, December 1, 2014 4:33:40 PM UTC+2, Tim Graham wrote:

Tim Graham

unread,
Dec 1, 2014, 12:08:01 PM12/1/14
to django...@googlegroups.com
I don't disagree this is a common source of confusion and the documented solution seems cumbersome.

In fact, I found a ticket about it: https://code.djangoproject.com/ticket/22203

We should move any discussion about solving the problem to django-developers instead of django-users though. Thanks!
Reply all
Reply to author
Forward
0 new messages