Django URLs
We created a view for our blog homepage in the previous chapter, and now we need to make that accessible to the browser by creating a URL for it. But first, let's learn a little bit about Django urls.
What is a URL?
A URL is simply a web address. You can see a URL every time you visit a website – it is visible in your browser's address bar. (Yes! 127.0.0.1:8000
is a URL! And https://djangogirls.org
is also a URL.)
Every page on the Internet needs its own URL. This way your application knows what it should show to a user who opens that URL. In Django we use something called URLconf
(URL configuration). URLconf is a set of patterns that Django will try to match with the requested URL to find the correct view.
How do URLs work in Django?
Let's open up the mysite/urls.py
file in your code editor of choice and see what it looks like:
mysite/urls.py
"""mysite URL Configuration
[...]
"""
from django.conf.urls import url
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
]
As you can see, Django has already put something here for us.
Lines between triple quotes ('''
or """
) are called docstrings – you can write them at the top of a file, class or method to describe what it does. They won't be run by Python.
The admin URL, which you'll visit in the following chapters, is already here:
mysite/urls.py
url(r'^admin/', admin.site.urls),
This line means that for every URL that starts with admin/
, Django will find a corresponding view. In this case we're including a lot of admin URLs so it isn't all packed into this small file – it's more readable and cleaner.
Regex
Do you wonder how Django matches URLs to views? Well, this part is tricky. Django uses regex
, short for "regular expressions". Regex has a lot (a lot!) of rules that form a search pattern. Since regexes are an advanced topic, we will not go in detail over how they work.
If you still wish to understand how we created the patterns, here is an example of the process – we will only need a limited subset of the rules to express the pattern we are looking for, namely:
^
for the beginning of the text$
for the end of the text\d
for a digit+
to indicate that the previous item should be repeated at least once()
to capture part of the pattern
Anything else in the URL definition will be taken literally.
Now imagine you have a website with the address like http://www.mysite.com/post/12345/
, where 12345
is the number of your post.
Writing separate views for all the post numbers would be really annoying. With regular expressions, we can create a pattern that will match the URL and extract the number for us: ^post/(\d+)/$
. Let's break this down piece by piece to see what we are doing here:
- ^post/ is telling Django to take anything that has
post/
at the beginning of the url (right after^
) - (\d+) means that there will be a number (one or more digits) and that we want the number captured and extracted
- / tells django that another
/
character should follow - $ then indicates the end of the URL meaning that only strings ending with the
/
will match this pattern
Your first Django URL!
Time to create our first URL! We want 'http://127.0.0.1:8000/' to be the home page of our blog and to display a list of posts.
We also want to keep the mysite/urls.py
file clean, so we will import URLs from our blog
application to the main mysite/urls.py
file.
Go ahead, add a line that will import blog.urls
. Note that we are using the include
function here so you will need to add that to the import on the first line of the file.
Your mysite/urls.py
file should now look like this:
mysite/urls.py
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'', include('blog.urls')),
]
Django will now redirect everything that comes into 'http://127.0.0.1:8000/' to blog.urls
and look for further instructions there.
Writing regular expressions in Python is always done with r
in front of the string. This is a helpful hint for Python that the string may contain special characters that are not meant for Python itself, but for the regular expression instead.
blog.urls
Create a new empty file named blog/urls.py
. All right! Add these first two lines:
blog/urls.py
from django.conf.urls import url
from . import views
Here we're importing Django's function url
and all of our views
from the blog
application. (We don't have any yet, but we will get to that in a minute!)
After that, we can add our first URL pattern:
blog/urls.py
urlpatterns = [
url(r'^$', views.post_list, name='post_list'),
]
As you can see, we're now assigning a view
called post_list
to the ^$
URL. This regular expression will match ^
(a beginning) followed by $
(an end) – so only an empty string will match. That's correct, because in Django URL resolvers, 'http://127.0.0.1:8000/' is not a part of the URL. This pattern will tell Django that views.post_list
is the right place to go if someone enters your website at the 'http://127.0.0.1:8000/' address.
The last part, name='post_list'
, is the name of the URL that will be used to identify the view. This can be the same as the name of the view but it can also be something completely different. We will be using the named URLs later in the project, so it is important to name each URL in the app. We should also try to keep the names of URLs unique and easy to remember.
Now visit http://127.0.0.1:8000/ and you should see the content you wrote in blog/templates/blog/index.html
.
Your console is showing an error but don't worry—they're actually pretty useful:
Your "about" page
It would be great if your blog had an 'about' section, where people could read more about you and your blog. Just as before, we first need to create a template for our page. Create a new file in blog/templates/blog
and name it about.html
. Inside, copy-paste the part of index.html
that we want to keep (we want the same styling, menu, and title).
blog/templates/blog/about.html
<html>
<head>
<title>Django Girls blog</title>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
<link rel="stylesheet" href="blog.css">
</head>
<body>
<div class="page-header">
<h1><a href="/">Django Girls Blog</a></h1>
</div>
</body>
</html>
Then add some information about yourself and about this blog after the <div class="page-header"></div>
. Get creative with your description, but make sure your file looks something like this when you're done:
blog/templates/blog/about.html
<html>
<head>
<title>Django Girls blog</title>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
<link rel="stylesheet" href="blog.css">
</head>
<body>
<div class="page-header">
<h1><a href="/">Django Girls Blog</a></h1>
</div>
<h2>Hi! My name is [your name] and I made this blog</h2>
<p>Here is a little bit more about me [...]</p>
</body>
</html>
After that, we need to create a new view. Add this new function to the bottom of blog/views.py
to tell Django that we want to use the about.html
template.
blog/views.py
def about(request):
return render(request, 'blog/about.html', {})
Just like before, this will render our template. What else are we missing? Right, we need to connect this view to an URL.
In your urlpatterns
you can add a new URL pattern for about
view by adding url(r'^about/$', views.about, name='about')
.
So now your blog/urls.py
should look something like this:
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.post_list, name='post_list'),
url(r'^about/$', views.about, name='about'),
]
Open http://127.0.0.1:8000/about/ in your browser to see if it worked.
If you receive a "Not found" error when you try to load the page, make sure you have added the
/
character at the end of the address bar in your browser. If that doesn't fix the problem, ask your coach for help.
Great job! You now have your very own website on your computer. Lets share it with the world.
If you want to know more about Django URLconfs, look at the official documentation: https://docs.djangoproject.com/en/1.8/topics/http/urls/