Page not found at /archive/ - django

EDIT: Figured it out, please see bottom.
I'm writing a simple blog app in Django and deploying it locally using this guide. I've completed the guide and everything was nominal so I decided to extend the functionality to view an archive of blog posts. This is how the index functions at the moment, but I wanted to move it to /archive/. I went to the tutorial again to get refresh my memory and it said I had to do three things:
Write the root URLconf in urls.py
Write the view function in views.py
Write the templates for the views
I edited the URLconf to look like this:
urlpatterns = patterns('',
#other patterns
url(r'^archive/', 'RehabLog.views.archive'),
)
I edited my views.py to add this function:
def archive(request):
posts = Post.objects.filter(published=True)
return render(request, 'RehabLog/archive.html', {'posts':posts})
I've saved it all and restarted foreman. When I load the page I get a 404 error which tells me No Post matches the given query. What am I missing out on?
Answer
I remembered reading the the order of your URLConfs was very important.
Previously I had:
urlpatterns = patterns('',
url(r'^admin/', include(admin.site.urls)),
url(r'^$', 'RehabLog.views.index'),
url(r'^(?P<slug>[\w\-]+)/$', 'RehabLog.views.post'),
url(r'^archive/', 'RehabLog.views.archive'),
)
Whereas now I have:
urlpatterns = patterns('',
url(r'^admin/', include(admin.site.urls)),
url(r'^archive/', 'RehabLog.views.archive'),
url(r'^$', 'RehabLog.views.index'),
url(r'^(?P<slug>[\w\-]+)/$', 'RehabLog.views.post'),
)
Which now works. Could anyone explain why?

/archive/ URL was first-matched by url(r'^(?P<slug>[\w\-]+)/$', 'RehabLog.views.post') so your actual rule url(r'^archive/', 'RehabLog.views.archive') was never reached. When you changed the order the first rule matched was the right one.

Related

Django URL regex with variables

Was hoping someone could point me in the right direction with this. I've tried nearly everything I can think of, but I can't seem to get it to work. I've got a set of URLs I'd like to match in Django:
www.something.com/django/tabs/
www.something.com/django/tabs/?id=1
Basically, I want to make it so that when you just visit www.something.com/django/tabs/ it takes you to a splash page where you can browse through stuff. When you visit the second URL however, it takes you to a specific page which you can browse to from the first URL. This page is rendered based on an object in the database, which is why the id number is there. I've tried to account for this in the URL regex, but nothing I try seems to work. They all just take me to the main page.
This is what I have in urls.py within the main site folder:
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^tabs/', include("tabs.urls")),
]
and within urls.py in the app's folder:
urlpatterns = [
url(r'\?id=\d+$', tab),
url(r'^$', alltabs)
]
Would anyone be so kind as to point me in the right direction? Thanks in advance!
You are not following the right approach here. Query paramers are used to change the behaviour of the page slightly. Like a added filter, search query etc.
What i would suggest is you have only one view and render different templates based on query parameters in the view.
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^tabs/', alltabs),
]
In your alltab views you can have something like this.
def alltabs(request):
if request.GET.get("id"):
id = request.GET.get("id")
your_object = MyModel.objects.get(id=id)
return render_to_response("tab.html", {"object":your_object})
return render_to_response("alltab.html")
Hope this helps
This is not the preferred 'django way' of defining urls patterns, I would say:-)
In the spirit of django would be something like
www.something.com/django/tabs/
www.something.com/django/tabs/1/
....
www.something.com/django/tabs/4/
and for this you define your url patterns within the app for example this way
tabs/urls.py:
from django.conf.urls import url
from . import views
urlpatterns = [
# ex: /tabs/
url(r'^$', views.index, name='index'),
# ex: /tabs/5/
url(r'^(?P<tab_id>[0-9]+)/$', views.detail, name='detail'),
# ex: /tabs/5/results/
url(r'^(?P<tab_id>[0-9]+)/results/$', views.results, name='results'),
]
and something similar in your views
tabs/views.py:
from django.shortcuts import get_object_or_404, render
from tabs.models import Tab
def index(request):
return render(request, 'tabs/index.html')
def detail(request, tab_id):
tab = get_object_or_404(Tab, pk=tab_id)
return render(request, 'tabs/detail.html', {'tab': tab})
...
You can follow this django tutorial for more details:

Django URL changes but doesn't render the proper view

I have a url setup with the following view (the url is in the app and the app urls are included in the project):
url(r'^details/(?P<outage_id>\d+)/$', 'outage.views.outage_details'),
def outage_details(request, outage_id=1):
outage_info = Outages.objects.filter(id=outage_id)
return render_to_response('templates/outage/details.html', {'outage_info': outage_info}, context_instance=RequestContext(request))
When I click on the link from http://localhost:8000 the url in the browser changes to http://localhost:8000/outage/details/1 as it should, but the view doesn't render the right template. The page stays the same. I don't get any errors, the url changes in the browser but the details.html template doesn't render. There is an outage in the DB with an ID of 1.
Any thoughts?
The regular expression r'^details/(?P<outage_id>\d+)/$' does not match the URL http://localhost:8000/outage/details/1. However, it should match the expression r'^outage/details/(?P<outage_id>\d+)/$'.
Perhaps, you can post your entire urls.py to find out which view is actually being called, since you don't get any errors. I suspect your home page is being called for all URLs.
Here is my url setup:
project/urls.py
urlpatterns = patterns('',
url(r'^$', 'outage.views.show_outages'),
url(r'^inventory/', include('inventory.urls')),
url(r'^outage/', include('outage.urls')),
url(r'^login', 'django.contrib.auth.views.login', {'template_name': 'templates/auth/login.html'}),
url(r'^logout', 'django.contrib.auth.views.logout', {'next_page': '/'}),
url(r'^admin/', include(admin.site.urls)),
)
outage/urls.py
urlpatterns = patterns('',
url(r'^', 'outage.views.show_outages'),
url(r'^notes/(?P<outage_id>\d+)/$', 'outage.views.outage_notes', name='notes'),
)
I have since changed the details to notes, since I had another page in a different app with a details url and I didn't want it somehow confusing things.

Having trouble separating urls.py

Hello I'm a newbie in Django.
I'm creating a blog app for practice and I wanted to separate the urls that relates to the blog application from the urls that relates to the other applications.
Since there are many blog-related url patterns, I just included in the main urls.py.
Here is my urls.py:
My_Project/My_Project/urls.py
urlpatterns = patterns('',
# Blog
url(r'^$', include('app_blog.urls'), name='app_blog'),
# Admin
url(r'^admin/$', include(admin.site.urls), name='admin_page'),
......
My_Project/app_blog/urls.py
urlpatterns = patterns('',
# Index page
url(r'^index/$', index_page),
# User page
url(r'^user/(?P<pk>\d+)/', UserDetail.as_view(), name='user_detail'),
......
So I expected that when I navigate to "www.example.com/index" the browser would show the index_page view and for "www.example.com/user/1", it will show the user detail view for user with id equal to 1.
For some reason, however, it shows the 404 page not found error for both pages.
Where have I gone wrong?
name parameter is for a single url pattern. Remove it from this line in My_Project/My_Project/urls.py
The regex pattern should not be '^$'. Instead just plain ''.
url(r'', include('app_blog.urls'))
The problem is here:
# Blog
url(r'^$', include('app_blog.urls'), name='app_blog'),
~~~
You are restricting your url to an empty path, that means everything that is not an empty path will not be matched against app_blog.urls.
Do this instead:
# Blog
url(r'^', include('app_blog.urls')),

urls.py structure for Django music app

I'm having some issues with the structuring of my Django app's urls.py file.
My project is a basic music player app. You begin by clicking a link for Music, followed by (for example) Artists, then you choose an artist, such as Weezer. The app then displays a list of albums and songs by that artist, rendered on the artist_name.html template by the views.artist_name function.
So far in the navigation of the app, the URL will look like http://localhost/music/artists/Weezer/.
My problem lies with the encoding of the next URL. If I choose the album The Blue Album by Weezer, I return the URL: http://localhost/music/artists/Weezer/The%20Blue%20Album.
This should render a template called artist_album_title.html using the views.artist_album_title function. Instead, it renders the new page using the same views.artist_name function as on the current page.
What seems to be happening is that the regex pattern for the ...Weezer/The%20Blue%20Album/ isn't matching with its related URL pattern in my urls.py file. Being new to Django (and with minimal experience with regex), I'm having a hard time determining what my urls.py file should look like for this kind of app.
Below is my urls.py file as it currently stands. Any help at all with my problem would be welcomed. Thanks guys.
from django.conf.urls import patterns, include
from music.views import home, music, artists, artist_name, artist_album_title
# Uncomment the next two lines to enable the admin:
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
(r'^admin/', include(admin.site.urls)),
(r'^$', home),
(r'^music/$', music),
(r'^music/artists/$', artists),
(r'^music/artists/([\w\W]+)/$', artist_name),
(r'^music/artists/([\w\W]+)/([\w\W]+)/$', artist_album_title),
)
artist_album_title function from views.py
def artist_album_title(request, album_title):
album_tracks = Track.objects.filter(album__title=album_title)
return render_to_response('artist_album_title.html', locals(), context_instance=RequestContext(request))
The problem with your urlpatterns is that the url /music/artists/Weezer/The%20Blue%20Album satisfies the first pattern so it doesn't go to the next one. This is because Django executes the patterns in the order they are specified.
In order for this to work you must switch the places of the two patterns like so:
urlpatterns = patterns('',
(r'^admin/', include(admin.site.urls)),
(r'^$', home),
(r'^music/$', music),
(r'^music/artists/$', artists),
(r'^music/artists/([\w\W]+)/([\w\W]+)/$', artist_album_title),
(r'^music/artists/([\w\W]+)/$', artist_name),
)
The best would be to use the following structure for your urls:
urlpatterns = patterns('',
(r'^admin/', include(admin.site.urls)),
(r'^$', home),
(r'^music/$', music),
(r'^music/artists/$', artists),
(r'^music/artists/(?P<artist_name>[\w\W]+)/(?P<album_title>[\w\W]+)/$', artist_album_title),
(r'^music/artists/(?P<artist_name>[\w\W]+)/$', artist_name),
)
and then your views definition will look like this:
def artist_album_title(request, artist_name,album_title):
and
def artist_name(request, artist_name):
you can read more about the named groups in the url in Django docs here
https://docs.djangoproject.com/en/dev/topics/http/urls/#named-groups

Difference between admin.site.root and admin.site.urls

In the The Django Book in chapter 6 about the Admin Site, they tell me to add the follwing URLpattern to urls.py:
urlpatterns = patterns('',
# ...
(r'^admin/', include(admin.site.urls)),
# ...
)
But to make it work on my system, I had to uncomment the following line:
(r'^admin/(.*)', admin.site.root),
Can somebody enlighten me on what the differences are?
Both Gabriel and Antti have it the wrong way round, unfortunately.
admin.site.root is the version 1.0 behaviour. If you have downloaded 1.0 or 1.0.2, that's what you should use.
However, there were some changes to the URL handling for Django's admin very recently, which are part of the yet-to-be-released 1.1. These are primarily to make it possible to use the reverse() function to look up admin URLs. So if you have a recent checkout of the code, you'll need to use admin.site.urls.
Your link is to the second edition of the Django Book, which is being updated for version 1.1 - and the docs which Gabriel refers to are also for the current checkout, which has the new version.
(Just for completeness, I'd note that versions of Django before newforms-admin was merged, prior to 1.0, used admin.urls, not admin.site.urls or admin.site.root.)
Please notice the following; I struggled because of (.*) being in the second entry below.
Works, but is deprecated:
urlpatterns = patterns('',
(r'^admin/(.*)', admin.site.root)),
)
Incorrect, and partially works:
urlpatterns = patterns('',
(r'^admin/(.*)', include(admin.site.urls)),
)
Correct, and works well:
urlpatterns = patterns('',
(r'^admin/', include(admin.site.urls)),
)
The Django Book speaks of version 0.9.6. Since then the admin has been rewritten. In Django 1.0 the whole admin is served by a single view (admin.site.root) which parses the rest of the URL internally.
Compare the admin directory of 0.96.3 with the corresponding directory from 1.0.2. There is no urls.py in the latter.
from the source code for the admin.site.root function:
root(self, request, url): Handles main URL routing for the admin app.
[...] method can be used as a
Django view function that presents a
full admin interface for the
collection of registered models.