Vadim Pushtaev
Vadim Pushtaev

Reputation: 2353

Match all urls without the prefix in Django

I'm currently using the following urls.py:

api_patterns = [
    url(r'^users/', include('users.urls', namespace='user')),
]

internal_patterns = [
    # ...
]

urlpatterns = [
    url(r'^api/', include(api_patterns)),
    url(r'^internal/', include(internal_patterns)),
    url(r'^admin/', include(admin.site.urls)),
    url(r'^(?!(?:api|internal|admin)/)', MainView.as_view()),
]

The point of this config is to render MainView if url doesn't have the api, internal or admin prefix:

How can I make it simplier and more intent revealing?

Upvotes: 4

Views: 2020

Answers (3)

mka
mka

Reputation: 173

For django >= 3 rather use re_path:

from django.urls import re_path

urlpatterns = [
    re_path(r'^.*',MainView.as_view())
]

Upvotes: 1

Derek Kwok
Derek Kwok

Reputation: 13058

I think your intent will be more clear if you do this in two urls:

url(r'^(api|internal|admin)/', SomeView.as_view()),
url(r'^.*', MainView.as_view())

MainView will be executed only if a url does not begin with api, internal or admin.

SomeView will be executed if a url begins with api/internal/admin but doesn't match the patterns above it. You can customize this view to either return a default 404 page, or perform other functions as you need.

Using your examples:

  • /api/users will execute include(api_patterns)
  • /api/foo will execute SomeView
  • /foo will execute MainView

Edit

To address the first point in your comment: url patterns are regexes, while you can extract these into variables to remove duplication, it can make code hard to read. Here's one example for removing duplication (I'm sure you can come up with others):

d = OrderedDict([
    (r'api', api_patterns),
    (r'internal', internal_patterns),
    (r'admin', admin.site.urls),
])

main_view_re = r'^!({})/'.format('|'.join(d.keys()))

urlpatterns = [url(r'^{}/'.format(k), include(v)) for k, v in d]
urlpatterns.append(url(main_view_re, MainView.as_view()))

Upvotes: 3

Gagandeep Singh
Gagandeep Singh

Reputation: 316

urlpatterns = [
    url(r'^api/', include(api_patterns)),
    url(r'^internal/', include(internal_patterns)),
    url(r'^admin/', include(admin.site.urls)),
    url(r'', MainView.as_view()),
]

Leaving no prefix would allow you to catch any URL that a user might try after the URL conf matches the api, internal and admin url's.

Upvotes: -2

Related Questions