Learning Web Development with Python and Django
Part 2
Welcome!
In Part 1 we made our first web-page with Django using function-based views.
In this tutorial, we will be learning how to use class-based views
which are more powerful and generally a better choice for web development. We will also look at html templates and creating multiple pages.
Class-Based Views
In the last tutorial, we used function-based views to determine what the client (visitor to the page) would see. However, there are also class-based views, which I will introduce to you now. These make creating views faster, especially when using databases, which we will be doing later.
Let's get started! Fork the basic template and rename it to tutorial-part-2
, or something else if you want.
Templates
Before we start creating our view, we need to learn about templates. In Part 1, our html was stored as a string,
html = "Hello, World!"
This is all right for very small pages, but when you want to make larger or more complicated pages, this gets very limiting. What would be better? If we made a file containing all of our html, and then imported that and displayed it.
To do this, we are going to create a folder called templates
. This will store all of our html templates for our website. Make sure you create your templates
folder outside of your main
folder, or Django will not be able to find it, like this:
Creating our first Template
Within templates
, create a file called home.html
. Then you can write some html inside it:
<!DOCTYPE html>
<html>
<head>
<title>Home</title>
</head>
<body>
<h1>Home</h1>
<p>Welcome to this website! This site was created using the web framework Django</p>
</body>
</html>
This is just some basic html. This isn't a html tutorial, but here is a quick line-by-line analysis:
<!DOCTYPE html>
tells the browser what type of file it is (html
)- The
<html>
and</html>
tags surround all the html - they show where it starts and ends - The
<head>
tag is used to put data in that isn't displayed on the page. Here I've put in the page title - this is shown in your tab at the top of the screen on your browser. - The
<body>
tags surround all the html that will be shown on the screen - The
<h1>
tag stands forheading 1
and means that it is the largest heading possible. You can also get<h2>
,<h3>
and so on, down to<h6>
. - The
<p>
tag surrounds a paragraph.
Now we've created our template, we can write our home page view.
Creating a Home Page View
Now we can create our class-based view! Navigate to views.py
and add the following code:
from django.views.generic import TemplateView
class HomePageView(TemplateView):
template_name = 'home.html'
Line 1
imports TemplateView
, which we will need to create our view.Lines 3-4
define our view class
- On
Line 3
we create our view, calledHomePageView
. This view inherits fromTemplateView
. This means we can use all the code fromTemplateView
as well as some code that we add that is specific toHomePageView
. - Here, the only thing that is specific about our home page is that it uses the template
'home.html'
, so onLine 4
we settemplate_name
equal to our template
That's it! All the rest is taken care of by the TemplateView
class, which the Django creators have written - so we don't need to worry about anything else.
Adding the URL (Page Name)
Finally, to give the view a url, we need to add it to the urlpatterns
in urls.py
:
from .views import HomePageView
urlpatterns = [
url(r'^admin/', admin.site.urls),
url('',HomePageView.as_view(), name='home')
]
This is pretty much all the same as last time (if you need a refresher, see Part 1). The only difference is that, for class-based views, we need to add a .as_view()
on to the end in order for the page to display.
...And it Works!
If you run the repl now, and open the page in a new tab, we get:
It worked!
How did Django know where to find the template?
If you've been paying close attention, you may be wondering - how did Django know where to find the template? In the view we just specified it as 'home.html'
, not as 'templates/home.html'
. The answer lies in settings.py
. If you open the file, you can see a list called TEMPLATES
:
# stuff
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# more stuff
TEMPLATES = [
{
# stuff
'DIRS': [os.path.join(BASE_DIR, 'templates')],
# more stuff
},
]
I have cut out the rest of the list to draw your attention to 'DIRS'
. What this code does is sets 'DIRS'
to the templates
folder that we created. Every time we request a template, Django will look in this folder. This code was put here by repl in case you wanted to create templates.
Making multiple pages
Now we are going to add another page - an About
page. To do this, we follow much the same process as we did for the home page.
Template
We create a file called about.html
in templates
:
<!DOCTYPE html>
<html>
<head>
<title>About</title>
</head>
<body>
<h1>About</h1>
<p>This is a tutorial for creating a web app with Django. Currently all we have done is made web pages</p>
</body>
</html>
View
Then we create a new view in views.py
:
# HomePageView
class AboutPageView(TemplateView):
template_name = 'about.html'
URL
And finally, we add the url in urls.py
:
from .views import (HomePageView, AboutPageView)
urlpatterns = [
url(r'^admin/', admin.site.urls),
url('about',AboutPageView.as_view(), name='about'),
url('',HomePageView.as_view(), name='home'),
]
The only thing to note from here is that the URL is now about
, which means that the page will be located at https://domain.name/about/. The URL for the about
page must be above the URL for the home page
because Django works through them from first to last, and because of the way it works, it matches ''
to all pages. However, if we put the about
before home
, it will check about
first, so if the client enters https://domain.name/about, it will be matched first, and the correct page displayed.
Extending Templates
The last thing we are going to learn in this (rather long) tutorial is a very useful built-in functionality of Django that allows template extension. What do I mean by this? An example is probably the best way to show it.
Create a new file in templates
called base.html
. This is going to be our base template. Add the following html to the file:
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}{% endblock title %}</title>
</head>
<body>
<a href="{% url 'home' %}">Home</a>
<a href="{% url 'about' %}">About</a>
{% block content %}
{% endblock content %}
</body>
</html>
And update your home.html
to look like this:
{% extends 'base.html' %}
{% block title %}Home{% endblock title %}
{% block content %}
<h1>Home</h1>
<p>Welcome to this website! This site was created using the web framework Django</p>
{% endblock content %}
Now, if you know anything about html, this will look very strange because it has all these {%
s which are not normally in html. There is quite a lot going on here, so I will walk you through it.
In base.html
:
- On
Lines 1-3
we have standard html - On
Line 4
we have our first strange occurrence of the{%
and%}
. What is happening here? This is Django's template language - designed for doing interesting stuff with your pages. Here we are declaring ablock
. This means that it is going to get replaced by something from another file - as you can see onLine 1
ofhome.html
, we are replacing it with the wordHome
. - On
Lines 7/8
there is also something happening. Here we are using Django'surl
function. Remember when we were defining our views, we set a name for them?
urlpatterns = [
url(r'^admin/', admin.site.urls),
url('about',AboutPageView.as_view(), name='about'),
url('',HomePageView.as_view(), name='home'),
]
The url
function gets the URL of the view with that name - so {% url 'home' %}
would get the URL of the home
page.
The <a href="
in html defines a link, so what we are creating here is a link to the home page, and then a link to the about page.
- On
Lines 10/11
we are creating ablock
called content, that will also be replaced by another file - inhome.html
we are replacing it with<h1>Ho...Django</p>
.
The home.html
imports the base.html
html using {% extends 'base.html' %}
, and then replaces what bits need to be changed.
If we run this, we get:
It worked!
The brilliant thing about these extensions is that they can apply to any pages - just update about.html
to this:
{% extends 'base.html' %}
{% block title %}About{% endblock title %}
{% block content %}
<h1>About</h1>
<p>This is a tutorial for creating a web app with Django. Currently all we have done is made web pages</p>
{% endblock content %}
And our about
page also has the links at the top! Also, the navigation means that we don't have to type in any more URLs, we can just click the links.
Conclusion
And that's the end of Part 2! I hope you enjoyed it. In Part 3 we will learn how to use databases with Django, as well as look at managing larger apps by splitting them up into smaller 'applets'.
Please upvote if you found this tutorial helpful, it supports me and lets me know that you want more! If you have any questions, post in the comments and I (or someone else) will answer them.
@ArchieMaclean Hi. This was working for me perfectly up until recently. I can't figure out what's wrong with it. I haven't changed anything. Can you please take a look. Help :( Thank you!!! https://repl.it/@oakwindicloud/TestPythonDjangoPart2
@oakwindicloud This seems to be a repl.it error - it is running the wrong command. There is a workaround, however!
Click run
, then after it has failed, you can type in another command into the terminal.
Type in python3 manage.py runserver 0.0.0.0:8000
.
That should start the server.
Note however that this can only be used for testing purposes (i.e. developing the site). If someone tries to access the website and you haven't ran that command in the last 30 minutes or so, they won't be able to.
If you want your site to run continually, you'll have to workaround with Polygott - do you want me to do this?
Hopefully this helps :)
@ArchieMaclean Thank you so much for your help. I’ve never used Polygott. How will that work?
@oakwindicloud Polygott is a repl type that allows you to run anything. You can create a Polygott repl at https://repl.it/languages/polygott
It would take quite a bit of file copying and debugging to get it working.
Actually, if you go to part 3 of this series, I introduce a new template - you might want to try using this template instead? It might work better.
It is quite good.
Hi, Is there a part 3? I can't find it from this page.
Great tutorial so far looking forward to more.
@stadham Hi! Part 3 is on its way - just having some difficulties and trying to work out some repl work-arounds. It should (hopefully) be out soon :)
Great! Thanks for doing this. Looking forward to it.
@ArchieMaclean Thanks so much
Thanks for the tutorial, it is very well explained.