I have an app, which I want to be the root of the website. So, I included the following urlpattern in my main urls.py like so:
(r'^$', include('search.urls')),
In my search urls.py, I have it set up in the following way:
urlpatterns = patterns('search.views',
(r'^$', 'index'),
(r'^results/$', 'results'),
)
The index urlpattern works, it goes to the index view, but the results urlpattern does not work. I get the following error when I try to access results:
Using the URLconf defined in textbook.urls, Django tried these URL patterns, in this order:
1. ^books/
2. ^$
3. ^admin/
4. ^static/(?P.*)$
The current URL, results/, didn't match any of these.
Edit:
main urls.py:
urlpatterns = patterns('',
(r'^books/', include('books.urls')),
(r'^$', include('search.urls')),
(r'^admin/', include(admin.site.urls)),
(r'^static/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT}),
)
Try this(put the searchurl include at the end and remove the $):
urlpatterns = patterns('',
(r'^books/', include('books.urls')),
(r'^admin/', include(admin.site.urls)),
(r'^static/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT}),
(r'^', include('search.urls')),
)
The reason for this is that the search urls will only be included if your path matches ^$, this means that only the / url will match this pattern since $ marks the end of the pattern. The last line of my urlconf says: forward everything else to the search urlconf (notice the absence of $). Note, anything you place after this line will never be matched, since this line matches anything.
Related
This should be an easy enough problem to solve for you guys:
I just started working with Django, and I'm doing some routing. This is my urls.py in the root of the project:
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('dashboard.urls')),
]
This is the routing in my dashboard app:
urlpatterns = [
path('dashboard', views.index, name='index'),
path('', views.index, name='index'),
]
Now let's say I want my users to be redirected to /dashboard if they go to the root of the website. So I would use '' as a route in the urls.py in the root, and then have everyone sent to /dashboard from the urls.py in the dashboard app. But when I do this I get the following warning:
?: (urls.W002) Your URL pattern '/dashboard' [name='index'] has a route beginning with a '/'. Remove this slash as it is unnecessary. If this pattern is targeted in an include(), ensure the include() pattern has a trailing '/'.
So I tried to use '/' instead of '', but since a trailing / is automatically removed from an url, the url wouldn't match the pattern. Should I ignore/mute this warning or is there another way to go about it?
This is the code that worked perfectly but gave me a warning earlier:
urlpatterns = [
path('/dashboard', views.index, name='index'),
path('', views.index, name='index'),
]
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('dashboard.urls'))
]
You can use RedirectView to redirect from / to /dashboard/. Then use 'dashboard' when including the dashboard urls.
urlpatterns = [
path('admin/', admin.site.urls),
path('', RedirectView.as_view(pattern_name='dashboard:index')
path('dashboard/', include('dashboard.urls')),
]
You can then remove 'dashboard' from the path in dashboard/urls.py, as it is already in the include().
app_name = 'dashboard'
urlpatterns = [
path('', views.index, name='index'),
]
I've added app_name='dashboard' to match the namespace used above in pattern_name='dashboard:index'.
Note that Django projects usually use URLs with a trailing slash, e.g. /dashboard/ instead of dashboard.
If you really want to use URLs like /dashboard without a trailing slash, then the include should be
path('dashboard', include('dashboard.urls')),
If you do this, I suggest you set APPEND_SLASH to False in your settings.
You can try something like this:
from django.conf import settings
from django.conf.urls import include, url
from django.contrib import admin
from django.views.generic import RedirectView
urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'^contacts/', include('appname.contacts.urls')),
url(r'^comments/', include('appname.urls')),
url(r'^subscriptions/', include('appname.partner.urls')),
url(r'^', RedirectView.as_view(url="/admin/"))
]
This is what I've done in my project so whenever the user go to 127.0.0.1:8000 it redirects to /admin
I simply want to get to another directory than index.
What I think Django is doing after I type in "localhost:8000/ysynch/":
Checking "ysynch/urls.py" (my root urls.py file)
Finding "ytlinks/" including "links.urls"
Matching with "ytlinks/" (in file "links.urls") and calling "views.ytlinks"
But instead, views.index is called. Where am I doing a mistake?
root\urls.py
C:\Users\xyron\Desktop\ysynch\ysynch\urls.py
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^ytlinks/', include('links.urls')),
url(r'^$', include('links.urls')),
]
links\urls.py
C:\Users\xyron\Desktop\ysynch\links\urls.py
urlpatterns = [
url(r'^ytlinks/', views.ytlinks, name='ytlinks'),
url(r'^$', views.index, name='index'),
]
Because paths are added to inclusion
url(r'^ytlinks/', include('links.urls')),
so you have following
# /ytlinks/ytlinks
url(r'^ytlinks/', views.ytlinks, name='ytlinks'),
# /ytlinks/
url(r'^$', views.index, name='index'),
so when you call /ytlinks/ you get to the view inside ytlinks which is index view again
the view you want to present is /ytlinks/ytlinks/
Checking "ysynch/urls.py" (my root urls.py file)
Finding "ytlinks/" including "links.urls"
Matching with "ytlinks/" (in file "links.urls") and calling "views.ytlinks"
The already matched part of the url will be excluded from further matching inside your includes.
So you basicly try to match "ytlinks/" again which would be true for "ytlinks/ytlinks/". You just want to match like this in your links\urls.py:
urlpatterns = [
url(r'^$', views.ytlinks, name='ytlinks'),
]
All of your urls in this file already match the first part "ytlinks/" and you only have to match the rest which is nothing or ^$ in your case.
The main part of your confusion is that you are expecting each urls.py to be trying to match the entire url, but instead you can think of include as doing a string concatenation and joining the previous parts of the url with the section of the url in the next urls.py
When django tries to match a url, it goes down the list of regexes until it finds one that matches so what you have is the following
r'^ytlinks/' + r'^ytlinks/' ==> views.ytlinks
r'^ytlinks/' + r'^$' ==> views.index
r'^$' + r'^ytlinks/' ==> views.ytlinks (not quite!)
r'^$' + r'^$' ==> views.index(not quite!)
So the first one of those that gets matched would be the second one for your url. $ in regex means end of a string so it won't bother to check anything that follows it here so you can rule out the last two regexes.
So your fix is threefold,
The links/urls you need to remove the first regex
url(r'^ytlinks/', views.ytlinks, name='ytlinks'),
You need to remove the $ from your inclusion url in the other urls.py
url(r'^', include('links.urls')),
You need to modify the views that each link should go to so eventually you end up with the following
root\urls.py
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^ytlinks/', include('links.urls')),
url(r'^', views.index, name='index'),
]
links\urls.py
urlpatterns = [
url(r'^$', views.ytlinks, name='ytlinks'),
]
Going to localhost/app works, but localhost/app/upload does not. Am I doing something really obviously wrong? I've tried a few different methods following the documentation without luck. I get a 404 saying the URL pattern does not match.
/project/app/urls.py
from app import views
urlpatterns = patterns('',
url(r'^$', views.view, name='result'),
url(r'^upload/$', views.upload, name='upload'),
)
/project/urls.py
urlpatterns = patterns('',
url(r'^admin/', include(admin.site.urls)),
url(r'^app/$', include('app.urls')),
)
Don't terminate the inclusion URL.
url(r'^app/', include('app.urls')),
I'm trying to use the Django sitemap framework to set up a sitemap but I'm getting an issue with setting up the sitemap URL.
Here is my projects urls.py
from django.contrib.sitemaps.views import sitemap
if settings.DEBUG:
import debug_toolbar
urlpatterns = patterns('',
url(r'^debug-toolbar/', include(debug_toolbar.urls)),
)
urlpatterns += patterns('',
url(r'^admin/', include(admin.site.urls)),
url(r'^sitemap\.xml$', sitemap, {'sitemaps': sitemaps}),
url(r'^robots\.txt$', TemplateView.as_view(template_name="robots.txt")),
url(r'^500/$', TemplateView.as_view(template_name="500.html")),
url(r'^404/$', TemplateView.as_view(template_name="404.html")),
url(r'^', include('hunt.urls')),
)
else:
urlpatterns = patterns('',
url(r'^admin/', include(admin.site.urls)),
url(r'^sitemap\.xml$', sitemap, {'sitemaps': sitemaps}),
url(r'^robots\.txt$', TemplateView.as_view(template_name="robots.txt")),
url(r'^500/$', TemplateView.as_view(template_name="500.html")),
url(r'^404/$', TemplateView.as_view(template_name="404.html")),
url(r'^', include('hunt.urls')),
)
Here is my hunt apps urls.py
urlpatterns = patterns('hunt.views',
url(r'^$', top100, name='top100'),
url(r'^explore/$', explore, name='explore'),
url(r'^monthly/$', monthlytop10, name='monthlytop10'),
url(r'^trending/$', trending, name='trending'),
url(r'^genres/$', genres, name='genres'),
url(r'^genres/(?P<slug>.+)/$', genre_view, name='genre_view'),
url(r'^contact/$', contact, name='contact'),
url(r'^contact/thanks/$', thanks, name='thanks'),
url(r'^faq/$', faq, name='faq'),
url(r'^songs/(?P<slug>.+)$', song_search, name='song_search'),
url(r'^loadmore/dj/$', loadmore_dj, name='loadmore_dj'),
url(r'^loadmore/genre/$', loadmore_genre, name='loadmore_genre'),
url(r'^loadmore/month/$', loadmore_month, name='loadmore_month'),
url(r'^loadmore/trending/$', loadmore_trending, name='loadmore_trending'),
url(r'^vote/dj/$', vote_dj, name='vote_dj'),
url(r'^vote/genre/$', vote_genre, name='vote_genre'),
url(r'^vote/month/$', vote_month, name='vote_month'),
url(r'^vote/trending/$', vote_trending, name='vote_trending'),
url(r'^(?P<slug>.+)/$', dj, name='dj'),
)
urlpatterns += staticfiles_urlpatterns()
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
When I try to access sitemap.xml I'm getting an error
404 Page Not Found
No DJ matches the given query.
This means it tried to access the last URL in my hunt app. Why is it trying to access the DJ Page even though it comes after sitemap.xml URL?
EDIT -
As per eran's suggestion, I ran the command show_urls of django_extensions. Here is the output of that
/ hunt.views.top100 top100
/404/ django.views.generic.base.TemplateView
/500/ django.views.generic.base.TemplateView
/<slug>/ hunt.views.dj dj
/contact/ hunt.views.contact contact
/contact/thanks/ hunt.views.thanks thanks
/explore/ hunt.views.explore explore
/faq/ hunt.views.faq faq
/genres/ hunt.views.genres genres
/genres/<slug>/ hunt.views.genre_view genre_view
/loadmore/dj/ hunt.views.loadmore_dj loadmore_dj
/loadmore/genre/ hunt.views.loadmore_genre loadmore_genre
/loadmore/month/ hunt.views.loadmore_month loadmore_month
/loadmore/trending/ hunt.views.loadmore_trending loadmore_trending
/media/<path> django.views.static.serve
/monthly/ hunt.views.monthlytop10 monthlytop10
/robots.txt django.views.generic.base.TemplateView
/sitemap.xml django.contrib.sitemaps.views.sitemap
/songs/<slug> hunt.views.song_search song_search
/static/<path> django.contrib.staticfiles.views.serve
/trending/ hunt.views.trending trending
/vote/dj/ hunt.views.vote_dj vote_dj
/vote/genre/ hunt.views.vote_genre vote_genre
/vote/month/ hunt.views.vote_month vote_month
/vote/trending/ hunt.views.vote_trending vote_trending
According to that show_urls output, the URLpattern for hunt.views.dj is taking precedence, because the r'^(?P<slug>.+)/$' regex appears before the sitemap.xml regex. The former regex will match a request to "sitemap.xml", so Django will never reach the pattern that's specifically meant for sitemap.xml. For that matter, it will never reach /contact/, /explore/, /faq/, etc.
I suspect that's happening because your project-wide urls.py appends to urlpatterns ("urlpatterns +=") rather than setting it directly. Looks like you didn't paste all of the imports from the project-wide urls.py, but I would assume one of the things you're importing includes a patterns object; otherwise you'd be getting a NameError at import time (name 'patterns' is not defined).
You should be able to fix it by changing this...
urlpatterns += patterns('',
...to this...
urlpatterns = patterns('',
But I have no way of knowing for certain, because I don't know what else you've imported in the project's urls.py.
I had a sitemaps.xml file in my templates folder that I was using before. Deleting that solved the issue.
I notice that your sitemap and robots.txt urls are the only ones that don't end in a trailing slash. Many web servers will redirect myurl.com/item to myurl.com/item/ - for example, this is the preferred practice when using Apache (search for "Trailing Slash Problem"). Try doing a curl to the url without a trailing slash - do you get a 301 redirect? If so then it is likely redirecting to the URL which DOES include a trailing slash, which is not matched by a pattern in your urls.py. Try adding trailing slashes to your regular expressions, or setting APPEND_SLASH = True in settings.py
Below is my django routing configuration:
# main module
urlpatterns = patterns('',
url(r'^api/', include('api.urls')),
)
# api module
urlpatterns = patterns('',
url(r'^$', views.index, name='index'),
url(r'^users/(?P<id>\d+)/?$', views.users, name='users')
)
I can access specific users (using ids) with http://localhost:8000/api/users/1/ but I can't access list of users: http://localhost:8000/api/users/:
Using the URLconf defined in duck_rip.urls, Django tried these URL patterns, in this order:
^api/ ^$ [name='index']
^api/ ^users/(?P<id>\d+) [name='users']
The current URL, api/users/, didn't match any of these.
Before this, I had my module urls like this:
url(r'^users/$', views.users, name='users')
and I had access to http://localhost:8000/api/users/. Can someone please explain me what is the error I make?
Just make id optional as:
url(r'^users/(?:(?P<id>\d+)/)?$', views.users, name='users')
And in view:
def users(request, id=None)