Our first task will be to get rid of the "Welcome to Django" message that displays as the home page. As stated in the message, Django only shows it because you have
DEBUG = True in your Django settings file and you haven't configured any URLs.
Let's dig deeper and really understand why the page shows and then we'd fix it.
When you navigate to http://127.0.0.1:8000/ a bunch of stuff happens. Here are the important things to note:
- Django determines the root URLconf. In this case it is given by the
src/yaba/settings.py, see here. It's
'yaba.urls'. Note how it's written as a string representing the full Python import path to your URLconf.
- Django locates the module-level variable
urlpatternsin the root URLconf, i.e.
src/yaba/urls.py, see here. It runs through each URL pattern, in order, and stops at the first one that matches the requested URL.
- Since no pattern matches, Django raises a subclass of the
Http404exception, see here.
DEBUG = True, Django handles the exception by displaying the welcome message, see here, here and here.
Let's fix it.
Prepare the workspace
Firstly, go to the Trello board for your project and move the card that tracks the "Add a home page" task from Todo to In Progress.
Note: We talked about how we'd be using Trello here.
Secondly, let's set up our git branches.
All the work we'll do will be based off a new branch we're calling dev.
Note: We'd only merge production ready code to master.
$ cd /path/to/yaba # Create a new branch called dev based off master $ git branch dev master
Let's create and switch to one now.
$ git checkout -b add-home-page dev
That command creates and switches to a new branch based off dev called add-home-page.
$ git branch * add-home-page dev master
Lastly, let's activate the virtual environment.
$ . venv/bin/activate
Add a home page
We want that when we navigate to http://127.0.0.1:8000/ that we see a custom home page.
src/yaba/urls.py and add a view and a URL pattern.
from django.conf.urls import url from django.contrib import admin from django.http import HttpResponse def home(request): return HttpResponse('Hello, world!') urlpatterns = [ url(r'^$', home), url(r'^admin/', admin.site.urls), ]
The home function above satisfies those requirements.
The newly added URL pattern uses the regular expression,
r'^$', to match the empty string and map it to the home view.
Why the empty string? I'm glad you asked :).
Django searches against the requested URL, as a normal Python string. This does not include GET or POST parameters, the domain name or the port.
Start up the server and navigate to http://127.0.0.1:8000/ to see the result.
(venv) $ python src/manage.py runserver
Great! We've accomplished our goal but we're not quite done yet.
A little about coding conventions
According to the Wikipedia article on coding conventions,
Coding conventions are a set of guidelines for a specific programming language that recommend programming style, practices, and methods for each aspect of a program written in that language. These conventions usually cover file organization, indentation, comments, declarations, statements, white space, naming conventions, programming practices, programming principles, programming rules of thumb, architectural best practices, etc.
Django, although not a programming language, also has coding conventions of its own. I won't list them here but rather point them out to you as we go along.
The importance of code conventions:
Code conventions are important to programmers for a number of reasons:
- 40%–80% of the lifetime cost of a piece of software goes to maintenance.
- Hardly any software is maintained for its whole life by the original author.
- Code conventions improve the readability of the software, allowing engineers to understand new code more quickly and thoroughly.
- If you ship your source code as a product, you need to make sure it is as well packaged and clean as any other product you create.
Put views in
One convention is to put your views in their own file, usually called
views.py. When working on your views you usually don't want to see or think about the URL mapping code or any other unrelated code for that matter. It also helps other developers to quickly find your views since they'd expect them to be in a
src/yaba and edit it to contain:
from django.http import HttpResponse def home(request): return HttpResponse('Hello, world!')
Now we need access to the view in
src/yaba/urls.py. Edit that to contain:
from django.conf.urls import url from django.contrib import admin from . import views urlpatterns = [ url(r'^$', views.home), url(r'^admin/', admin.site.urls), ]
This is much better.
Let's look at what's returned when we access the page through
$ curl http://127.0.0.1:8000/ Hello, world!
Notice that there's no doctype, no html, head or body tags. Only, "Hello, world!". Django doesn't add that stuff for us. If we want valid HTML then we have to write it ourselves.
Here's one way to get what we want:
home_html = '''<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Yet Another Blog</title> </head> <body> <p>Hello, world!</p> </body> </html> ''' def home(response): return HttpResponse(home_html)
And here's the
curl output now:
$ curl http://127.0.0.1:8000/ <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Yet Another Blog</title> </head> <body> <p>Hello, world!</p> </body> </html>
However, as you might imagine, writing huge chunks of HTML in your code like that is frowned upon :(.
The kosher way is to use templates but we'd leave that for another time.
Let's wrap up.
Stop the server and commit the changes.
$ git add . $ git commit -m "Add a home page"
We're done with this feature so let's merge it into the dev branch.
$ git checkout dev $ git merge add-home-page
You may delete the feature branch if you so desire.
$ git branch -d add-home-page
Finally, go back to your Trello board and move the "Add a home page" card from In Progress to Done.
For your reference, here's a diff of all the work we did in this post: yaba/add-home-page.
The overall goal was to add our own home page. First we took the time to understand how Django rendered a view when we accessed a given URL.
Using that knowledge we added our own view in the simplest way possible.
However, that caused us to get a mini lecture on coding conventions.
So we refactored the code to follow the Django convention of placing views in their own file.
After inspecting the content returned for the page we noticed that we weren't returning valid HTML and so we fixed it by updating the response.
We didn't write much code but a lot of important concepts were discussed.
Hopefully you learned a few new things.
P.S. What did you learn? Am I teaching too many ideas at once? Do I need to slow down or speed up? Let me know in the comments below.