Django urldispatcher: directing the request to special view - django

Django=3.0.8
urls.py
urlpatterns += [
path('<slug:categories>/', include('categories.urls', namespace="categories")),
]
categories/urls.py
urlpatterns = [
path('', CategoryGeneralView.as_view(), name='general'),
re_path(r'^(?P<type>novosti|tema)$/',CategorySpecialView.as_view(), name="type"),
path('draft/<slug:slug>/', PostDetailView.as_view(), name="draft_post_detail"),
path('<slug:slug>/', PostDetailView.as_view(), name="post_detail"),
]
Problem
When I input either of
http://localhost:8000/windows/tema/
http://localhost:8000/windows/novosti/
the request goes to PostDetailView. But I want it to go to CategorySpecialView.
How can I achieve this?

Why not just use 2 separate paths, i.e.:
path('novosti/', CategorySpecialView.as_view(), name = 'type'),
path('tema/', CategorySpecialView.as_view(), name = 'type'),

Related

How to include part of the url patterns from an Django app

I have two django apps with URLs
app_name = 'app1'
urlpatterns = [
path('url1/', ..., name='name1')
path('<slug:username>/', ..., name='name2')
]
and
app_name = 'app2'
urlpatterns = [
path('url2/', ..., name='name3')
path('<slug:username>/action2/', ..., name='name4')
]
This would not work if I include them in the master urlpatterns as
urlpatterns = [
path('', include('app1.urls'),
path('', include('app2.urls'),
]
because url2/ would first match <slug:username>/ and trigger an error for unknown username.
There are a few potential solutions but none works very well for me:
Use non-slug url2 such as ~url2. That means all urls in app2 has to start with something like ~ or ^.
Redefine some URLs in the master urlpatterns but then I will have to import views from the apps and remove urls from the app urlpattern.
Use regular expression to explicitly exclude some names from the <slug:username>. This could work but then any changes in app2 urlpatterns need to be reflected in app1's <slug:username> ... exclude certain names.
It is possible to do something like
urlpatterns = [
path('', include('app1.urls'), # non-user part
path('', include('app2.urls'), # non-user part
path('', include('app1.urls'), # user part
path('', include('app2.urls'), # user part
]
so that fixed-name URLs will be matched before <slug:username>?
From Django docs:
include((pattern_list, app_namespace), namespace=None)
Parameters:
pattern_list – Iterable of path() and/or re_path() instances.
app_namespace (str) – Application namespace for the URL entries being
included
You can include specific urls with this method:
urlpatterns = [
path('', include(([path('url1/', <YourViewName>)], 'app1'))),
path('', include(([path('url2/', <YourViewName>)], 'app2'))),
path('', include(([path('<slug:username>/', <YourViewName>)], 'app1'))),
path('', include(([path('<slug:username>/action2/', < YourViewName >)], 'app2'))),
]
First element of tuple inside include is the list of path/re_path instances that you want to include, and the second one is the app name.

Django set default empty url

I'm trying to learn Django and I'm following Corey Shafer's tutorials (https://www.youtube.com/watch?v=a48xeeo5Vnk), but when I try to make two different pages, I get automatically directed to the one with an "empty address":
In his:
/Blog
/urls.py
it looks like this:
from django.conf.urls import path
from . import views
urlpatterns = [
path('', views.home, name='blog-home'),
path('about/', views.about, name='blog-about'),
]
and when he goes to localhost:8000/blog/about, the page displays correctly
When I try to imitate his code for blog/urls.py:
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'', views.home, name='blog-home'),
url(r'^about/', views.about, name='blog-about'),
]
the result of the localhost:8000/blog/about is the content of views.home, and not views.about.
The following works correctly, when I write a name instead of an empty string:
urlpatterns = [
url(r'^home', views.home, name='blog-home'),
url(r'^about/', views.about, name='blog-about'),
]
But I don't understand why it worked in a previous version, why it won't work now, and what could fix it
A url matches if it can find a substring that matches, the empty string r'' thus matches every string.
You should make use of anchors to specify the start (^) and end ($) of the string:
urlpatterns = [
# &downarrow; &downarrow; anchors
url(r'^/$', views.home, name='blog-home'),
url(r'^about/', views.about, name='blog-about'),
]
Note: As of django-3.1, url(…) [Django-doc] is
deprecated in favor of re_path(…) [Django-doc].
Furthermore a new syntax for paths has been introduced with path converters: you
use path(…) [Django-doc] for that.

Path is not match any of these

I always get this error "The empty path didn't match any of these." When I try to access the page through this url:
url('^about/$',views.AboutView.as_view(),name = 'about')
and when I remove "^about/$" part, then it works:
url('',views.AboutView.as_view(),name = 'about')
How could I resolve it?
This is link for call:
<li><a class="navbar-brand" href="{% url 'about'%}">About</a></li>
this is view.py
class AboutView(TemplateView):
template_name = 'about.html'
and, this urlpatterns
urlpatterns = [
url('^about/$',views.AboutView.as_view(),name = 'about')
]
from django.conf.urls import url
from blog import views
urlpatterns = [ url('about',views.AboutView.as_view(),name='about') ]
instead of this
from django.urls import path
from blog import views
urlpatterns = [
path('about/', views.AboutView.as_view(),name='about'),
use this pattern same as your main url
path('about/', views.AboutView, name='about'),
It's not good to follow 2 ways of creating urls, Since django==2.0 they have introduced very nice and easy way to declare urls.
In the old way...
from django.conf.urls import url
urlpatterns = [
url(r'^about/$', AboutView.as_view(), name="about")
]
But In the new way it's lot more cleaner...
from django.urls import path
urlpatterns = [
path('about/', view.AboutView.as_view())
]
But if you want to stick with the regular expressions, Use re_path() instead of path().
urlpatterns = [
re_path(r'about/$', view.AboutView.as_view())
]
In my it's better stay with one pattern, old or new but not both. It makes your code look more cleaner.

Django url/route order not maintained

I have the following in my root URLconf module (there's more, but not important, so left out):
urlpatterns = [
re_path(r'^password-reset-redirect-view/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
password_reset_redirect,
name = 'password_reset_confirm'),
path('', include('search.urls')),
path('', include('customer_portal.urls')),
path('rest-auth/', include('rest_auth.urls')),
path('rest-auth/registration/', include('rest_auth.registration.urls')),
Here's the customer_portal.urls:
urlpatterns = [
path('customer/contact/', views.contact),
path('', views.home),
re_path(r"^confirm-email/(?P<key>[-:\w]+)/$", views.email_verification,
name="account_confirm_email"),
]
Here's the rest_auth.registration.urls:
urlpatterns = [
url(r'^$', RegisterView.as_view(), name='rest_register'),
url(r'^verify-email/$', VerifyEmailView.as_view(), name='rest_verify_email'),
url(r'^account-confirm-email/(?P<key>[-:\w]+)/$', TemplateView.as_view(),
name='account_confirm_email'),
]
As you can see both included urls.py urlpatterns have a view named 'account_confirm_email'.
Somewhere in the code this is ran:
url = reverse(
"account_confirm_email",
args=[emailconfirmation.key])
Since customer_portal.urls is included before rest_auth.registration.urls, I expect the route account_confirm_email in customer_portal.urls to be returned by the above reverse method. But instead I get the rest_auth.registration.urls route URL.
Just to be sure I commented out the route in rest_auth.registration.urls, and then I did get the correct URL (customer_portal URL) returned.
It is filled into an email, I check that email and see that I have the wanted url: http://127.0.0.1:8000/confirm-email/......./, instead of: http://127.0.0.1:8000/rest-auth/registration/account-confirm-email/...../
Can anyone tell me why the customer_portal URL isn't the one being reversed in both cases?
Django docs say:
Django runs through each URL pattern, in order, and stops at the first one that matches the requested URL.

One out of all urls is not matching

I'm using Django 1.8 and I can't figure out why one particular url isn't getting matched.
The url is /weapons. Django is adding a trailing slash to it which I believe is because of the APPEND_SLASH option being true by default. Even if I try to reach the url without the slash it will fail then try the slash.
This is the error I get:
top level urls.py
urlpatterns = [
url (r'^admin/', include (admin.site.urls)),
url (r'^', include ('core.urls', namespace = 'core')),
url (r'^', include ('equipment.urls', namespace = 'equipment')),
]
core urls.py
urlpatterns = patterns [
url (r'^$', views.index, name = 'index'),
]
equipment urls.py
urlpatterns = [
url (r'^equipment$', views.index, {'type':'index'}, name = 'index'),
url (r'^weapons$', views.index, {'type':'weapons'}, name = 'weapons'),
url (r'^armor$', views.index, {'type':'armor'}, name = 'armor'),
url (r'^accessories$', views.index, {'type':'accessories'}, name = 'accessories'),
]
I would do:
urlpatterns = [
url (r'^admin/', include (admin.site.urls)),
url (r'^home/', include ('core.urls', namespace = 'core')),
url (r'^equipment/', include ('equipment.urls', namespace = 'equipment')),
]
and
urlpatterns = [
url (r'^weapons/$', views.index, {'type':'weapons'}, name = 'weapons'),
]
note the [] instead of patterns in django 1.8
your url would look like:
http://localhost:1000/equipment/weapons/
which makes sense right?
Try to remove leading ^ from urls in core/urls.py and equipment/urls.py.
Turns out it was a caching issue. I tried it using Ctrl + F5 but it didn't work so I tried the page in Incognito mode which worked. So I used the Developer Tools to reload the page and now it works.