- 5.1 Introduction
- 5.2 The Purpose of Views and URL Configurations
- 5.3 Step-by-Step Examination of Django's Use of Views and URL Configurations
- 5.4 Building Tag Detail Webpage
- 5.5 Generating 404 Errors for Invalid Queries
- 5.6 Shortening the Development Process with Django View Shortcuts
- 5.7 URL Configuration Internals: Adhering to App Encapsulation
- 5.8 Implementing the Views and URL Configurations to the Rest of the Site
- 5.9 Class-Based Views
- 5.10 Redirecting the Homepage
- 5.11 Putting It All Together
5.10 Redirecting the Homepage
If you run Django’s development server and navigate to the root of the website, you’ll discover that we’ve missed a spot, as shown in Example 5.72.
Example 5.72: Shell Code
$ ./manage.py runserver
Browsing to http://127.0.0.1:8000/ will display an error page telling us the URL configuration doesn’t have a route for this page. While we’ve created a very detailed and clean URL configuration for all of our URLs, we’ve omitted the homepage, the root of our website.
We want to show the list of blog posts on the homepage. There are several ways we can go about doing so.
5.10.1 Directing the Homepage with URL Configurations
The first and perhaps most obvious way would be to create a new URL pattern to send the route to the view we have already built. In /suorganizer/urls.py, we could add the URL pattern shown in Example 5.73 to the URL configuration.
Example 5.73: Project Code
suorganizer/urls.py in 3ddb5f3810
20 from blog.views import PostList . ... 23 urlpatterns = [ 24 url(r'^$', 25 PostList.as_view()), . ... 29 ]
The regular expression pattern: ^ starts the pattern, while $ ends the pattern. This matches '', which is what the root of the URL is to Django, given that it always strips the first /.
Similarly, given that the PostList view is the root of the blog URL configuration, the URL pattern could also be as shown in Example 5.74.
Example 5.74: Project Code
suorganizer/urls.py in 4dc1d03a79
23 url(r'^$', include(blog_urls)),
Neither of the solutions presented above is desirable, as they both corrupt the cleanliness and simplicity of our site URLs. In the first instance, http://site.django-unleashed.com/blog/ and http://site.django-unleashed.com/ are now exactly the same. In the second case, we have created an entire branch of URLs, which is far worse. Not only are http://site.django-unleashed.com/blog/ and http://site.django-unleashed.com/ the same page, but so is http://site.django-unleashed.com/blog/2013/1/django-training/ and http://site.django-unleashed.com/2013/1/django-training/ (note the missing blog/ in the second URL path). This will effectively create a duplicate of every URL the blog already matched.
Our website should maintain a clean URL scheme. Short of creating a separate homepage view, directing our homepage to an existing view as above is undesirable.
5.10.2 Redirecting the Homepage with Views
Rather than simply displaying a webpage on our homepage, we will instead redirect the user to the desired URL. In this instance, http://site.django-unleashed.com/ will redirect to http://site.django-unleashed.com/blog/, which is the post_list() view.
To redirect a URL, we need a view. This creates a minor problem: we are redirecting our site-wide homepage with a view, which at this point exists only in app directories. However, this code does not belong in either our organizer or blog apps. Although Django does not anticipate the need for site-wide views.py, nothing is stopping us from creating /suorganizer/views.py. Inside, we write the code shown in Example 5.75.
Example 5.75: Project Code
suorganizer/views.py in 2e8036623d
1 from django.http import HttpResponseRedirect 2 3 4 def redirect_root(request): 5 return HttpResponseRedirect('/blog/')
The HttpResponseRedirect class is a subclass of HttpResponse with special properties, just like HttpResponseNotFound. Given a URL path, it will redirect the page using an HTTP 302 code (temporary redirect). Should you wish for an HTTP 301 code (permanent redirect), you could instead use HttpResponsePermanentRedirect. Note that doing so in development can result in unexpected behavior because the browser will typically cache this response, resulting in difficulties should you change the behavior.
In /suorganizer/urls.py, we can import the new view and replace our previous URL pattern with the one in Example 5.76.
Example 5.76: Project Code
suorganizer/urls.py in 2e8036623d
22 from .views import redirect_root 23 24 urlpatterns = [ 25 url(r'^$', redirect_root), . ... 29 ]
Running the deployment server with $ ./manage.py runserver and navigating a browser to http://127.0.0.1:8000/ will result in a redirect to http://127.0.0.1:8000/blog/.
The behavior is what we desire, but our implementation could be improved. Instead of using HttpResponseRedirect, we can use a Django shortcut, redirect(). Our /suorganizer/views.py will now look like Example 5.77.
Example 5.77: Project Code
suorganizer/views.py in 5fb0dff63a
1 from django.shortcuts import redirect 2 3 4 def redirect_root(request): 5 return redirect('/blog/')
The code in Example 5.77 will work exactly as if we were still using HttpResponseRedirect, with an HTTP 302 code. Should we wish to switch to an HTTP 301 code, we could pass permanent=True to the shortcut, as in: redirect('/blog/', permanent=True).
The advantage to redirect() is that, unlike HttpResponseRedirect, it does not need a URL path (currently used in Example 5.77). To better adhere to the DRY principle, we can instead use the name of the URL pattern we wish to redirect to, as shown in Example 5.78.
Example 5.78: Project Code
suorganizer/views.py in ba8c7c5e89
4 def redirect_root(request): 5 return redirect('blog_post_list')
The shortcut in Example 5.78 is exactly what we want, but it may be a little opaque. Unlike the shortcuts we’ve seen before, we don’t currently understand everything going on under the hood. Specifically, we don’t know how the shortcut builds a proper URL path from the URL pattern. We will see exactly how to do this in the next chapter and revisit this shortcut then.
Note that our way of redirecting, with a site-wide function view, is not the way you would redirect in an actual project. Our method is in direct violation of DRY, but we won’t be able to fix that until Chapter 17.
In short, the behavior above is exactly what we want, and the code is the best we can write given our current knowledge. Please keep this function and behavior in mind going forward, as we will revisit it in Chapter 6 and replace it in Chapter 17.