in my application I’ve got a view called download_document which works fine using {% url ‘download_document’ some_id %} .
Installing a 3rd party app into the virtual environment cause trouble because this app has also the download_document view (also accepting one ID parameter) with the same urlname.
If I’d like to use both with this name, can I somehow make the difference between them? For instance using both cases in the same template file?
Python: 2.7
Django: 1.11.16
Debian .
Update #1:
my app is called infk . I tried already using
{% url 'infk:download_document' document.id %}
, but in this case I got a 500 with: u’infk’ is not a registered namespace.
I also tried adding namespace to the top urls.py file:
#original
url(r'^infk/', include('infk.urls')),
#modified
url(r'^infk/', include('infk.urls', namespace="infk")),
but in this case i got back a different 500: Reverse for ‘infk’ not found. ‘infk’ is not a valid view function or pattern name.
To work the second one I’d need to change at least all reverse methods from ** reverse(‘infk’…) to reverse(‘infk:infk’…) which I don’t really want.
So if I don’t add namespace, is there any way to call my download_document function? (By default it calls the 3rd party app’s download_document view .
2
Answers
There is a way to avoid
url
name conflicts. All you have to do is to add their respective namespaces before theurl
name. As per the docs, all you need is the following:By using the namespaced URL resolution strategy.
Long post ahead, so deep breath…
That depends on what you’re trying to do. If you always want your download_document function to be called throughout your entire website (even on the pages provided by the 3rd-party-app), you can just move infk to the end of your
urlpatterns
inmain_app/urls
. That would look something like this:Otherwise, if you’re trying to get your download_document in specific instances without namespaces, it’s not particularly easily. You could create a custom tag that always produces the url for your download_document function, but that’s a lot of extra work, and if you run into another name conflict, you’d have to do it again and again, and that’s barely a step above hard-coding the url in the first place. Plus, if you’re planning to deploy infk as a third party app, you’ll probably want to use a namespace to help other people avoid the same problem you’re having.
Explanation
According to the docs at https://docs.djangoproject.com/en/1.11/topics/http/urls/#naming-url-patterns:
So if you change the order of your included urls in your main_app/urls.py file such that infk is after the 3rd-party app, you should get the infk download_document. However, this means that you’ll ALWAYS get the infk download_document, which may break some of the functionality in your 3rd-party app.
Examples
Django 1.x
Source: https://docs.djangoproject.com/en/1.11/topics/http/urls/#reversing-namespaced-urls
Your modified
url(r'^infk/', include('infk.urls', namespace="infk"))
has created an instance namespace, which might make sense if you are using multiple instances of infk throughout your app. If you aren’t (or you’re planning on deploying infk as a third-party app itself) you probably don’t need that. Either way, I’d recommend you set the application namespace.Instance Namespaces
Instance namespaces would be called like this:
You should still be able to get the 3rd-party download_document url, if you need it. Note that in order for this to work, 3rd-party-app.urls must be included AFTER infk.urls.
Application Namespaces
The behavior of application namespaces depends on whether there are instance namespaces defined for the application or not, and whether the view called defines a current_app. If you use the above example where both application and instance namespaces are defined, then using an application namespace in your
{% url %}
tag may return inconsistent results. (See https://docs.djangoproject.com/en/1.11/topics/http/urls/#reversing-namespaced-urls for more information)For ease of explanation, I’m going to assume you are not using multiple instances of the infk app. Your main_app/urls.py might then look like:
Application namespaces are called like this:
And, assuming that 3rd-party app is installed AFTER infk, your 3rd-party app’s download_document can still be called like:
Django >=2.x
Source: https://docs.djangoproject.com/en/dev/topics/http/urls/#term-application-namespace
The resolver works essentially the same as described above; however, instead of using
url()
in your urls.py files, usepath()
orre_path()
.