In Django 1, I used to have the following URL mappings:
...
url(r'^main/', include('main.urls', namespace='main')),
url(r'.*', include('main.urls'))
The r'.*' mapping is always at the last line to take care of all kinds of URLs not mapped.
In Django 2, the following mappings are used instead:
path('main/', include('main.urls', namespace='main')),
re_path('.*', include('main.urls')),
Although it also works, yet Django complains:
?: (urls.W005) URL namespace 'main' isn't unique. You may not be able to reverse all URLs in this namespace
Giving the second mapping another namespace is not working. Any solutions?
try writing a view to redirect to main/ and then include the view in your urls:
re_path('.*', views.redirect_view)
In that case you can use django.views.generic.base.RedirectView to simply redirect to the said url without importing it twice.
urlpatterns = [
path('main', include('main.urls')),
re_path('.*', RedirectView.as_view(url='main/your_default_url_in_main_url'), name='main'),
]
Try to remove the trailing slash of 'main/' and change to 'main'.
Note: If your main.urls looks like this
urlpatterns = [
path('/whatever1', view1),
path('/whatever2', view2),
]
You have to pick where to redirect the default view by supplying RedirectView.as_view(url='main/whatever1') to redirect to view1 as default. use 'main/whatever2' to redirect to view2 as default
reference: RedirectView
Related
Supposed my views.py contain multiple views that are meant to go deeper in the url path.
urlpatterns = [
path('<int:table_pk>/order/', views.menu_category_view, name='menu_category_view'),
path('<str:menu_category>/', views.menu_item_view, name='menu_item_view'),
]
The first view has the path generated as <int:table_pk>/order/.
If I want the second view to have a path as following <int:table_pk>/order/<str:menu_category>/, how should i go about passing the variables (in the view and/or template) in DRY manner?
What if I have more path levels that need to extend the path above it in this same manner?
You can work with an include(…) clause [Django-doc]:
from django.urls import include
urlpatterns = [
path('<int:table_pk>/order/', include([
path('', views.menu_category_view, name='menu_category_view'),
path('<str:menu_category>/', views.menu_item_view, name='menu_item_view'),
]))
]
The path(…) before the include(…) is thus common for both path(…)s in the list wrapped in the include(…).
You can thus construct a hierarchy by using includes where a path(…) can be wrapped in an include(…) of another path(…), etc.
My url patterns look like this:
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('api.urls')),
re_path('.*', IndexView.as_view()),
]
This works but it matches all URLs, including those prefixed with admin and api. I want those URLs to still match, and for any unmatched URLs to render IndexView.
Before 2.0 I used this regex for this purpose. I tried using it in re_path but that didn't work, which is what led me to trying the above.
url(r'^(?P<path>.*)/$', HtmlView.as_view())
Use case is a SPA where I handle 404s client side.
Many thanks in advance.
You can use two entries (one for '/', another one for anything else), but using path for both of them, which should be (slightly) more efficient:
urlpatterns = [
path('', IndexView.as_view(), {'resource': ''}),
path('<path:resource>', IndexView.as_view())
]
In this case, I'm using <path:resource> because path catches all resource names, inluding that with / in them. But it does not capture the main index resource, /. That's why the first entry. The dictionary as last argument for it is because we need to provide a resource parameter if we want to use the same view than in the second entry.
That view, of course, should have 'resource' as a paremeter:
def as_view(request, resource):
...
So as I said in the question description, trying the regex I was using before Django 2.0 in re_path did not work. It would basically match for all requests except / (i.e., index path). I fixed this by using both that regex and a second path matching / specifically. Here's the code:
urlpatterns = [
re_path(r'^(?P<path>.*)/$', IndexView.as_view()),
path('', IndexView.as_view()),
]
With these changes my other routes would match and these two routes would account for all other urls.
One Idea to go about this is let the django catch 404.
url.py
from django.conf.urls import handler404
handler404 = 'app_name.views.bad_request'
and in your views.py
views.py
def bad_request(request):
return redirect(reverse('home'))
You can always do some regex thingy to catch unmatched urls. but hey this gets the job done. :)
I get this error message
Using the URLconf defined in esarcrm.urls, Django tried these URL patterns, in this order:
1. ^person/ duplicate_check/(?P<entity>)/(?P<full_name>)/?$
2. ^admin/
3. ^api/v1/
4. ^api/v1/authenticate/$ [name='api_authenticate']
5. ^static\/(?P<path>.*)$
6. ^media\/(?P<path>.*)$
The current path, person/duplicate_check/candidate/tom, didn't match any of these.
Please not the space here 1. ^person/[SPACE]duplicate_check
my project/urls.py
urlpatterns = [
url(r'^person/', include('person.urls')),
url(r'^admin/', admin.site.urls),
url(r'^api/v1/', include(router.urls)),
url(r'^api/v1/authenticate/$', crm_views.ApiAuthenticateView.as_view(), name='api_authenticate'),
]
my app.urls
urlpatterns = [
url(r'duplicate_check/(?P<entity>)/(?P<full_name>)/?$', views.check_if_exist),
]
my app.views
#api_view(['GET'])
def check_if_exist(request, entity, first_name):
if entity == 'candidate':
candidates = person_models.Candidate.objects.filter(first_name=first_name)
serializer = person_serializers.CandidateMiniSerializer(candidates, many=True)
return Response(serializer.data)
What exactly am I missing?
There is no space, that's just how Django prints the URLs.
The problem has nothing to do with spaces, but with your URL. "duplicate_check" is included under person/, but you are trying to access p_check/....
Edit There are actually bigger problems with your URL pattern. You haven't actually given the capturing groups anything to capture. You need some kind of pattern inside the parentheses. Something like:
r'^duplicate_check/(?P<entity>\w+)/(?P<full_name>\w+)/?$'
which will capture all alphanumeric characters for entity and full_name.
urlpatterns = [
url(r'^$', predict_views.index, name = 'HomePage'),
url(r'^admin/', admin.site.urls),
url(r'^Update_db/$', predict_views.Update_db, name = 'Update_db'),
url(r'^compare/(?P<phone1_id>[0-9]+)/(?P<phone2_id>[0-9]+)/$',predict_views.Compare, name = 'Compare'),
url(r'^predict/(?P<phone_id>[0-9]+)/$',predict_views.Predict, name = 'Predict'),
]
these are my url patterns in djano. I want to go to compare directly from predict which is not possible for me currently because :
when I go to predict the url is 127.0.0.1:8000/predict/1 now when i go to compare from predict the url becomes 127.0.0.1:8000/predict/1/compare/1/2 which is not the expected url .. my url should be 127.0.0.1:8000/compare/1/2
I have seen django docs there are some redirect methods but I do not understand them.
Any help is appreciated.
Something tells me you are accidentally using relative urls. In your template, try the following:
Compare Page
I noticed that in Django there are two formats of urlpatterns in file urls.py:
urlpatterns = [
url(...),
url(...),
]
and
urlpatterns = pattern('',
url(...),
url(...),
)
The first is a list of url instances, and the second invokes the pattern module with an empty string and a number of url instances as parameters.
What is the difference between the two?
What is the purpose of an empty string in the second format?
Which one is recommended to use?
In Django 1.8+, urlpatterns should simply be a list of url()s. This new syntax actually works in 1.7 as well.
urlpatterns = [
url(...),
url(...),
]
The old syntax using pattern is deprecated in Django 1.8, and is removed in Django 1.10.
urlpatterns = pattern('',
url(...),
url(...),
)
With the old syntax, you could provide a prefix. The example given in the docs is
urlpatterns = patterns('news.views',
url(r'^articles/([0-9]{4})/$', 'year_archive'),
url(r'^articles/([0-9]{4})/([0-9]{2})/$', 'month_archive'),
url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', 'article_detail'),
)
However, using strings arguments for the view is now deprecated as well, and you should provide the callable instead.
Per the documentation, patterns is:
A function that takes a prefix, and an arbitrary number of URL
patterns, and returns a list of URL patterns in the format Django
needs.
The first argument to patterns() is a string prefix.
It also provides an example of why you might want to use it:
from django.conf.urls import patterns, url
urlpatterns = patterns('',
url(r'^articles/([0-9]{4})/$', 'news.views.year_archive'),
url(r'^articles/([0-9]{4})/([0-9]{2})/$', 'news.views.month_archive'),
url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', 'news.views.article_detail'),
)
In this example, each view has a common prefix – 'news.views'.
Instead of typing that out for each entry in urlpatterns, you can
use the first argument to the patterns() function to specify a
prefix to apply to each view function.
With this in mind, the above example can be written more concisely as:
from django.conf.urls import patterns, url
urlpatterns = patterns('news.views',
url(r'^articles/([0-9]{4})/$', 'year_archive'),
url(r'^articles/([0-9]{4})/([0-9]{2})/$', 'month_archive'),
url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', 'article_detail'),
)
However, note that this function is deprecated:
Deprecated since version 1.8:
urlpatterns should be a plain list of django.conf.urls.url() instances instead.
Note that the explanation as to why includes (with good reason, clearly!):
Thus patterns() serves little purpose and is a burden when teaching
new users (answering the newbie’s question "why do I need this empty
string as the first argument to patterns()?").