How to Deal with Namespacing URLs in a Reusable Dj

2019-07-30 02:44发布

问题:

I have been struggling with reversing URLs with a reusable Django app. Here's the basic layout of my problem.

Reusable App:

In the urls.py file it has the following pattern:

url(r'^object-list/$', ObjectListView.as_view(), name='object-list')

Somewhere in the reusable app's views.py, there is the following reverse call:

reverse('object-list')

My Project:

In the project where I want to use this app, I have another conflicting view name, so I namespace the app's URLs like so:

url(r'^app-stuff/', include('app.urls', namespace='app'))

The Problem:

This has the consequence of causing all reverse calls within the app to throw a NoReverseMatch exception when it tries to lookup object-detail, because the URL now has the name app:object-detail.

I have access to the app in question, so I can modify the calls it makes to reverse, but I would like to do it in a way that doesn't involve hardcoding a namespace. I have read the documentation on the current_app and namespace arguments to the include function but I don't quite understand if they would help solve the issue I'm having.

Any suggestions you might have are greatly appreciated.

回答1:

I solved this after reading Django's docs on URL resolution more closely.

If you have a reusable app called myapp, you can add the property app_name to its URL configuration to give it an application namespace. Example:

# myapp/urls.py

app_name = 'myapp'

urlpatterns = [
    url(r'^index/$', IndexView.as_view(), name='index')
]

Now, even if the app's URLs are included like so:

# project/urls.py

urlpatterns = [
    url(r'^myapp/', include('myapp.urls', namespace='random-namespace')),
]

...the urls are still accessible using reverse('myapp:index').

If you would like to see this in more detail, I created a small GitHub repo with an example.

Edit:

Specifying the app_name property in urls.py only works on Django 1.9 and up. For Django 1.8, you have to use the app_name parameter in the include() function.