Super Crash Course in Full Stack Web Development with Python and Django

Disclaimer

Throughout my self teaching, I have used many different resources, mainly so I can know what topics are important to include. One of the great things about the programming community is the open source nature, of which people have complete ability to copy anything that is free on this website and do what they want with it. I did not directly copy any other work while writing this book. However, if I have inadvertently copied someone else’s work, please let me know and I will give the proper attribute.

I am not the only person to create guides for Django and web development. The following are great resources to learn more and answer any questions you may have:

In addition, there may be some elements that are inaccurate, or there may be typos. If you notice anything, please let me know as well.

Introduction

This book was written to be a very broad crash course in Full Stack Web Development in Python. It covers a lot of topics and tries to dive into each one sufficiently. However, each of these topics could (and do) have an entire book written on them.

I tried to write this to give a written crash course/bootcamp that can be used as a reference for those who have never programmed, or have never done web design. Part of the problem of learning is not knowing where to start. This book will touch on many topics that should be learned by programmers if they want to get into web development. It should act as an outline and an introduction to many of these skills. When you are done, you will be able to create a pretty significant amount of code, but this should only be the beginning of your learning. Unfortunately, you will not be an expert by the end of this book. Programming changes so rapidly that it is very difficult to stay current, so you will constantly be learning.

In order to fully learn the content of this book, you should make sure to code along with the examples as much as you can. In addition, you should try changing and playing with the examples to see how it affects different parts of your code. This will help you get a firmer grasp on the concepts. It would be ideal to be able to do that in real time in this book, but it makes it quite difficult without an accompanying video.

I also tried to make sure this book has standalone chapters. If somebody just wants to learn Python, they can focus on the Python chapters. This is different in the case of the Django chapter, because it is project based over a few chapters. Now, there may be necessary overlap, but some concepts, such as loops and logic are repeated in multiple chapters in different languages. Because a lot of the concepts are the same, the text will be nearly identical, but it will have different syntax.

Javascript is not covered in this book, however. I have realized that many different crash courses teach Javascript and JQuery, but I have rarely used it in a practical setting, as most of what I need to do can typically be accomplished via CSS and the backend. This is not to say that Javascript is not widely used. There are many different Javascript libraries and frameworks that are widely used, and many are among the most popular, including React, Angular and Node. However, that is beyond the scope of this course. Learning Javascript will not really have a lot of applicability in the context of this book, but I will be writing more material that leverages the power of Javascript.

Lastly, this book tries to focus on concepts rather than memorization. Memorization will come with practice. I try to explain the concepts more than the specific applications of the concepts, as there are plenty of resources online that can be used as a reference.

Terms that will be used

We will be using a lot of potentially new terms in this book. Terms will be brought up with each concept, but the following are ones that you should know ahead of time.

Syntax is the way a programming language is written. Each programming language has a different way of writing the same task. Python has a different syntax than Javascript, for example. The logic in each programming language is very similar, if not identical. The syntax is the thing that changes, and the biggest part of the learning curve when learning a new programming language if you already know how to code.

Front End Development is the programming of the user facing part of the website. You may also hear the term "Client Side."

Back End Development is the part of web design that focuses on the website beneath the surface. This includes working with databases and the data itself. You may also hear it called "Server Side."

What is Programming?

Programming, or coding, is simply a way of writing down a list of instructions that you want the computer to do. As a programmer, you can think of yourself as a translator. Instead of translating from one person’s language to another person’s language, you are translating from human to computer. That is really all it comes down to.

Ten Commandments of Coding

In order to learn how to program, there are a few things that you should keep in mind. I compiled a list of rules that are widely considered to be important during your programming career. I did not come up with these myself, and you will probably see these rules repeated by many different people.

  1. Don’t repeat yourself

  2. Keep it simple, stupid (KISS). This can also be described as "less code is better than more code" or "simple is better than complex."

  3. Keep consistent naming and style conventions throughout each project

  4. Make sure your code is scalable

  5. Make sure your code is readable

  6. Try not to get intimidated when looking at new code

  7. Don’t reinvent the proverbial coding wheel - if code

  8. Comment, Comment, Comment!

  9. Understand that you won’t have all the answers - use the Internet!

  10. Practice, practice and practice again

What if I have questions?

You will likely have questions while going through this book. The resources I listed in the disclaimer are great for any questions you may have. In addition, don’t be afraid to go to the source’s documentation and read it. Lastly, Google is your friend. If you have a question, chances are somebody else also has. I can’t tell you how many random error messages I just copied and pasted into Google and found a Stack Overflow thread on it.

Good luck!

HTML

What is HTML?

HTML, or Hypertext Markup Language is the language of the internet. When you open up a web page, you are essentially opening up a .html file. The browser "converts" the markup that you write in your text editor to a user friendly format.

Think about a .doc or .docx file. When you are creating a .doc or .docx file, you are using a word processor to actually show the content of your file, such as Microsoft Word. If you were to open your file in Notepad, for example, it would look very different. But - it is the same file! It is just using a different program to display it.

That is the same with a browser. A browser takes your .html file and creates the user friendly version of it. You could open the .html file in Notepad, or any text editor, and it will look much different. That is what learning how to programing in HTML is - working in a text editor to display something to a browser for an end user.

Note
You may see the word "client" throughout this book or on other learning platforms. The client is also known as the user. Furthermore, when we say "client side," we mean the part of the website that the user, or client, sees. "Client side" and "Front End" are essentially interchangeable.

This chapter will be very visual, so if you like pictures, this is the chapter for you. I will be showing you snippets of code, but I will also show you how it should look in your browser.

How to Use HTML

HTML is very, very easy to get started with, so let’s jump right in. First, create a new text document. In Windows, this can be done by right clicking on your desktop, going to "New" then clicking "Text Document". You can name the document whatever you would like.

Now that you have created it, you can double click to open it. Once you have it open, click "File" then "Save-As". In the "File name" input, type "Webpage.html". Then, in the "Save as type" input, click the drop down and select "All Files" Finally, click "Save."

Creating a new text document
Figure 1. Creating a new text document
Save a document as .html
Figure 2. Save as .html

Congratulations! you have just created your first .html document! Type the following code in your html file and save it:

<h1>Hello World!<h1>

Next copy and past the path that your file is saved in and paste it in the URL in your browser. You should see the following in your browser:

Hello World in Browser
Figure 3. Hello World in Browser

You are now a web developer! Right now, you are essentially hosting your web page, called "Webpage.html" on your own computer. Websites are similar - they just save it on another location. Then, when you go to a website, the browser will show whatever .html file is at that location. In the case of the above example, the file is located at C:/Users/tanner/desktop/webpage.html.

Now, let’s dive into HTML a little more. HTML documents are broken up into different elements. One example of an element is an <h1> element (called a tag). The <h1> tag is one of the most basic HTML tags, and it is formatted as a large heading in a web page (Heading 1).

Self Closing vs Non-Self Closing Tags

As you saw, there are three parts of the <h1> tag.

  1. The opening part: <h1>. This part opens the tag and lets you know that the following content will be a Heading 1.

  2. The content: Hello World. This part is the actual meat of the element.

  3. The closing tag: </h1>. This closes the tag, so the content is wrapped between these two snippets. Everything outside these snippets will be formatted in their own way.

Generally speaking, tags will have an opening and closing element. For example, if you wanted a Heading 2 element, you would type the following:

<h2>Hello World!<h2>

I encourage you to type that into your .html file, resave and refresh your browser to see what happens.

Not all tags will require the ending tag. There are some tags that are self closing, such as the <input /> tag. In these cases, there is no content to be wrapped, and all code will be put within the tag. We will see both throughout this chapter, so it is important to know that this is common, and it will make more sense as we go along.

Common Tags

We briefly introduced tags in the last chapter, so we will go more in depth of ones that you will likely use in your programming career. Let’s first start off with how to properly create an .html document. The entire .html file should always be wrapped in a <html> tag. Within the <html> tag, there are two other tags, the <head> and <body> tags. Put the following code in your "Webpage.html" file:

<html>
    <head>
        <!-- Content in the head goes here. On a side note, this notation is for comments. -->
    </head>
    <body>
        <!-- Most content will go here -->
    </body>
</html>

The <html> tag is basically used to tell the browser that this is indeed an html document. We see two more elements, the <head> tag and the <body> tag. The <head> tag is where most of the high level html content will go. A great analogy I have heard before is to think of the <head> tag as your head. That is where all of your higher level thinking goes.

The <body> tag is where the rest of the content goes. This is where the content will go that the user/client will see. For beginning HTML-ers, we will mainly be focused on the <body> tag. At this moment, your webpage is empty. There is no actual content, just empty elements.

The one exception for the time being is the <title> tag. Within the <head> tag, the <title> tag will change the actual name of the html document that appears in your browser. In Google Chrome, this will be what appears on the tab. Right now, it is just "Webpage.html".

If you change your code in the <head> tag to the following:

<head>
    <title>My Webpage</title>
</head>

You will see that the name in your tab is now "My Webpage".

There are a lot of tags in HTML. Remember the Ten Commandments of Coding: Try not to get intimidated when looking at new code. This will be showing you a lot of them, but do not worry if you cannot memorize them right away. That will come with time while you practice.

Heading and Paragraph Tags

We have already looked at <h1> tags. This element will be the largest of the Headings in your project. HTML actually has 6 Heading elements, which are <h1> through <h6>. A common way to see this is to type the following within the <body> in your html document. See W3 Schools to interactively learn this.

<h1>This is a Heading 1 Element.</h1>
<h2>This is a Heading 2 Element.</h2>
<h3>This is a Heading 3 Element.</h3>
<h4>This is a Heading 4 Element.</h4>
<h5>This is a Heading 5 Element.</h5>
<h6>This is a Heading 6 Element.</h6>
<p>This is a Paragraph Element.</p>

Your webpage should now look like the following:

Headings
Figure 4. Headings

Cool, right? This is a simple way to change the size of your text in a web page. Notice I put in a <p> tag in as well. This tag is very common and is used to type normal text. We will learn in the following chapters how exactly to format a better website, but this is great for now.

Styling Tags

From now on, we will be using <p> to write our normal text. HTML has support for simple styling of your text including bold and italic. As you have seen before, we can nest elements inside of each other. The <head> and <body> elements are inside the <html> element, and we put more content within the <body> element. We can go further by putting more tags within a paragraph element.

<p>Sometimes I like to <strong>bold</strong> text and other times I like to <em>italicize</em> text.</p>

If you put this into your "Webpage.html", save it and refresh your browser, it will look like this:

Styling
Figure 5. Styling

As you can see, the <strong> tag will bold any text within it and the <em> tag will italicize any text within it.

Links are going to be another very common element in your webpage. A link is simply a way to navigate to another webpage, whether it is part of your website or an external webpage. The way to do this is using the <a> tag. Before we can jump in, however, we need to learn another concept - tag attributes.

An attribute is code that is put within the tag itself. Attributes is where we really start to see the power of HTML. Look at the following code, for example:

<a href="https://www.google.com">Go to Google</a>

Let’s dissect this code. The content is "Go to Google". This will be what appears as text in your webpage. However, what does "href" mean? This is an attribute that tells the hyperlink where to go when the content is clicked. If you put the above code in your webpage, save and refresh your browser, you should see the following:

Hyperlink
Figure 6. Hyperlink

You now have a link that will take you to Google!

Note
You will need to add "http://" or "https://" before your link in the href attribute in order to go to an external website. Otherwise, it will assume it is located in the same location you are. Try to remove the "https://" before "www.google.com" and see what happens when you click your link. This will make more sense as we go through the book.

I suggest practicing with a few different <a> tags to learn how it works with different websites.

Images

Images are the first self closing tag we will look at. It is denoted by the following:

<img src="beach.jpeg" />

It uses an attribute src, which tells the tag where the image is and the name of the image. It assumes that the image is in the same folder that the html file is. Once we start building larger webpages, we will look into this more. At this point, it just adds the "beach.jpeg" source to the end of the current directory. This makes sense with the note in the previous section about links.

I have a file called "beach.jpeg" in the same folder as my "Webpage.html" file, so when I put that code in my file, I get the following:

Image
Figure 7. Image

Lists

What if you want to make a list of items? Well, HTML has something for that. There are two types of lists - ordered lists and unordered lists.

Ordered Lists

An ordered list is a list of items that is numbered. The syntax is as follows:

<ol>
    <li>My First Item</li>
    <li>My Second Item</li>
    <li>My Third Item</li>
</ol>

You wrap your list with the <ol> and create each list item by wrapping them in <li>.

When you refresh your browser, you should see the following:

Ordered List
Figure 8. Ordered List

You now have a list of items that are numbered.

Unordered Lists

Unordered Lists have similar syntax, but will create a bulleted list.

<ul>
    <li>My First Item</li>
    <li>My Second Item</li>
    <li>My Third Item</li>
</ul>

The only difference is the outside wrapping tag. It is <ul> instead of <ol>. Lists can have as many items as you would like.

Tables

What if you want a table? That is also very easy in HTML. A table is simply the intersection of rows and columns that create cells. In HTML, you can create a table with the following code:

<table>
    <tr>
        <th>City</th>
        <th>State/Region</th>
        <th>Country</th>
    </tr>
    <tr>
        <td>Los Angeles</td>
        <td>California</td>
        <td>United States</td>
    </tr>
    <tr>
        <td>Prague</td>
        <td>Prague</td>
        <td>Czech Republic</td>
    </tr>
    <tr>
        <td>Rome</td>
        <td>Lazio</td>
        <td>Italy</td>
    </tr>
<table>

Let’s break that down a little bit. The entire table is created using <table>. Then, within that, there are rows of the table, denoted by <tr>. The number of columns is given by how many data points are in each row, <td>. In this case, there are three columns. The heading of each column are denoted by <th>. This is the name of the column, and by default, HTML makes this stick out. Your webpage should look like this now.

Table
Figure 9. Table

Now that we have tables, we can move onto forms, one of the most important features you will need to know for web development.

Forms

You will use forms a lot while you are developing websites. Forms are everywhere on the internet, from the place you type in your Google search to when you log into your e-mail account. Forms are created using the <form> tag and all of the inputs are <input /> tags. The <input /> tag is another self closing tag, and has an attribute of type. By defining the type, you will output different types of inputs. That does not make sense without an example, so let’s look at the following text:

<form>
    <p>Username</p>
    <input type="text" placeholder="Username"/>
    <p>E-mail</p>
    <input type="email" placeholder="Email"/>
    <p>Password</p>
    <input type="password" placeholder="Password"/>
    <p>Date</p>
    <input type="date" />
    <br />
    <input type="reset" />
    <input type="submit" value="Submit Input"/>
</form>

Before we go forward, I want to introduce a new tag, <br />. This tag will create a new line in your webpage.

Now, let’s look at the types of inputs.

  1. text: This is a simple input that takes plain text.

  2. email: This is similar to the text input. However, it is a new type that will validate whether or not you have an email address in the input. When you click "submit", it will check if it is in the format of an email address.

  3. password: Password type will create a hidden input so people cannot see your password when you are typing it in.

  4. date: A choice of dates.

  5. reset: It will empty the current form.

  6. submit: It will submit the current field. This has another attribute called value, which will show what text to put in the button.

The placeholder attribute says what text will be in the input temporarily until the User begins input. At this point, your webpage should look like the following:

Form
Figure 10. Form

There is another cool feature in HTML - required. By adding required in your HTML inputs, you will be able to validate that the input is not empty. The syntax is as follows:

<input type = "text" required />

That is all. If you were to try to submit a form with this syntax, the front end would prevent you from submitting. Give it a try.

Now, we will look at a few more input types - radio and check boxes.

<form>
    <input type="radio" value="roption1" name="radio-options" /> Option 1 <br />
    <input type="radio" value="roption2" name="radio-options" /> Option 2 <br />
    <input type="radio" value="roption3" name="radio-options" /> Option 3
</form>

<form>
    <input type="checkbox" value="coption1" name="check-options" /> Option 1<br />
    <input type="checkbox" value="coption2" name="check-options" /> Option 2<br />
    <input type="checkbox" value="coption3" name="check-options" /> Option 3<br />
</form>

Radio buttons have radio inputs that will only allow one choice for each group, by default. Checkbox buttons will allow more than one option for each group, by default.

The value attribute will tell the database what value the user is returning. The name attribute tells the database what form is being used. Note that we appended the Options at the end of the input. This is just for a user experience, so that the content for "Option 1", "Option 2" and "Option 3" have a corresponding User Interface with the value attribute. When we start dealing with back end development, this will start making more sense, as the values will correspond to the data in the database.

Your webpage should look like the following:

Radio and Check Boxes
Figure 11. Radio and Check Boxes

End of Chapter

We have covered a lot in this chapter. Do not feel like you need to memorize everything at once. Many things we learned will be used more than others, so it will just come with practice. There are a few very important tags that we still need to cover, but it would not make as much as sense without CSS, which we will cover in the next chapter.

CSS

What is CSS?

CSS, or Cascading Style Sheets, is what makes websites look good. You can think of HTML as the person, and CSS as the clothing. CSS adds styling to otherwise boring websites.

Google without styles
Figure 12. Google without styles

Using Chrome’s development tools, I very cumbersomely and grotesquely started deleting the CSS files and Javascript files (we will learn more in later chapters). What you see on the left side is basically the same HTML, but it does not have many of the CSS and Javascript files. You will see the same HTML tags and elements, but the format, layout and style of the website will look much different. In Safari, you can easily select to disable the stylesheets, and you can do this yourself.

This chapter will be very visual, like the last one. CSS is still part of Front End Development, so changes will be directly visible in the browser. Let’s get started!

Divs, Spans, Ids and Classes

Divs and Spans

As we said at the end of the last chapter, there were some tags that we did not cover yet. Those two tags are <div> and <span>. Both tags are used to separate different content for styling purposes. <div> is generally used for larger blocks of code, while <span> is typically used for short chunks of code (a sentence or less). They can work together as the following:

<div>
    This text is in the div, but outside of the span.
    <span>This text is inside of the div and the span.</span>
</div>
<div>
    This text is in the second div, but outside of the second span.
    <span>This text is inside of the second div and the second span.</span>
</div>

The code results in the following:

Divs and Spans
Figure 13. Divs and Spans

Notice how the code is shown on the page. There is no real styling, but the second div does go to another line, while the spans stay on the same line. This is because of the display property. Each html tag has different properties and corresponding values for those properties in CSS. So, display is a CSS property that says how the elements will behave from a layout basis.

A <div> has a default display value of block. This means that it will take up its own line. If we have three <div> tags, one after another, by default they will take up their own line, and the next <div> will go to the next line, as we can see in Figure 13.

<span> elements have a default display value of inline. Inline elements will just flow with the page. In the previous example, the <span> within the <div> stays on the same line as the other content within the div.

The display property is very important to keep in mind and can result in a lot of anger when trying to get a layout designed in a web page (not speaking from personal experience, of course). Another possible value for display is inline-block. An inline-block element behaves as an inline element, but it is more flexible. We will see more of this as we go along. Another value is none. A display value of none does exactly what it sounds like; it will remove the element from view.

IDs and Classes

Ids and classes are HTML tag attributes that can help add style to an element. It allows a programmer to refer to a specific element (often time a div or a span) or group of elements to apply styling to them.

<div class="red-background">
    <span id="text">My text</span>
</div>

I can then go into CSS and refer to the div called "red-background" and the span called "text". Classes are typically used for more than one item, and IDs are used when you are referring to one specific element.

CSS Syntax

All that is great, but what does this mean for me? How do I actually start using classes and ids to style? Create a new .html file and type the following:

<html>
    <head>
        <style type="text/css">
        </style>
    </head>
    <body>
        <div class="red-background">
            <span id="text">My text</span>
        </div>
    <body>
</html>

We have introduced the <style> tag. This is called "Internal CSS," because it is located inside of the html document. We will also learn how to use "External CSS," which keeps all of your styling in another document (which is the most common way to style). For the time being while we learn syntax, all of our CSS code can be put in the <style> tag.

Let’s start styling. Within the style tag, we can refer to the div by class and span by id by typing

<style type="text/css">
    .red-background{
        background-color: red;
    }
    #text{
        color: white;
    }
</style>

Let’s walk through this. In order to refer to a class in our CSS, we type a . then the class name. In order to refer to an id, we type a # then the id name. After we choose our class or id, we create a code block for all of our styles for that class or id, by using curly braces. Within these curly braces, we put property, value pairs, separated by a colon, and then finished by a semi-colon. We can put as many property, value pairs as we want in each block.

The red-background class has a background-color property, for which its value is red. The text id has a color: white; style, which sets the color of the font.

If you save your html file and refresh your browser, you will see the following:

CSS Styling
Figure 14. CSS Styling

Notice how the red color spans the entire width of the browser. This is because the div is a block element, and takes up an entire line. So, it will fill the entire div with a background color of red. Try deleting the background-color property in the class and put it in the text id styling and see what happens.

As we saw, CSS has a specific syntax. Generally speaking, the syntax is

tag-name{
    property-1: value-1;
    property-2: value-2;
    ...
    property-n: value-n;
}
.class-name{
    property-1: value-1;
    property-2: value-2;
    ...
    property-n: value-n;
}
#id-name{
    property-1: value-1;
    property-2: value-2;
    ...
    property-n: value-n;
}

Note the first example - you can also add styles to an entire tag, such as a div or span. You can have as many properties as you want and you can name your classes and ids whatever you want, although there are naming conventions that we will cover. At this point, you just want it to be very clear what your class does and which element your id refers to.

Internal, Inline and External CSS

A quick aside - CSS can be created in the same file, called internal CSS. This uses the <style> tag that we previously discussed within the <head> of the file.

We can also set the style within the html in the tag using the following syntax:

<div style = "color: red; background-color: black;">
    This content has a black background with red text.
</div>

You can put as many properties you want separated by semi-colons.

However, both of these methods are cumbersome. The most common way is to use external CSS. External CSS is CSS that is stored in another file, and then linked to in the html file. Let’s say you have a CSS file named styles.css in the same folder as your html file. You would implement the CSS by using the following syntax:

<link rel = "stylesheet" href = "styles.css" />

The href will be the path of your external CSS file. External CSS links will typically go in the <head> as well.

The Box Model

Every HTML element can be looked at as a box. You can think of the text and everything that is closed within the tag as the content. The content is the center of the box. Outside of the box is called padding. Padding is the space between the content and the border of the element. If you want the border to be far away from the content, you increase the padding. Or, if you want the border to be hugging the content closely, you decrease the padding. Then, you hit the border, which is exactly what it sounds like - the border of the element.

The last part of the box is the margin. It may be easy to think of the margin as the part right outside of the element. It determines how much space is between the HTML element and the next HTML element.

Box Model
Figure 15. Box Model

If you have two <h1> elements, and you want them far apart, you can increase the padding. However, if you gave them a border, the borders would be close to each other. If you gave them a big margin, the borders would not be touching, and would be separated by the margins.

Units

When you are assigning values to properties, it is important to understand the important of units. Colors can be created with different methods. Depending on your project, you will want to use different units for things such as font-size or height.

Color

When setting a property that has a color value, there are three main ways to do it:

  1. Using HTML’s built in color values, such as black or red.

  2. Using rgb(r, g, b). If you want to give a color value to a property, a common way to do this is by typing the rgb() function with corresponding values for the red, green and blue values. For example, white is rgb(255,255,255).

  3. Use rgba(r, g, b, a). If you want to change the opacity of the color (how transparent it is), rgba() is used, where a is between 0 and 1, where 0 is transparent, and 1 is completely opaque.

  4. Use hex codes. You can look more into them on the internet, but hex codes are another way to set values for colors. It will start with a number sign followed by an alphanumeric value. For example, white is #ffffff.

You would use these the following ways:

background-color: rgb(0, 0, 0);
background-color: rgba(0, 0, 0, .5);
background-color: #aaaaaa;

All of those are the same way to set the background color to black. The rgba one, however, makes it 50% transparent.

Lengths and Sizes

When something has a length, height or any type of size value, there are a few different ways to set them. These are the most common:

Table 1. Summary of Lengths and Sizes
Syntax Explanation Syntax

Pixels

The number of pixels you want the element to be

font-size: 10px;

em

This is a relative length that will give a multiple of the current font size. For example, if the current font size is 10px, 2em would be 20px.

font-size: 3em;

rem

This is widely used in responsive design. The browser has a "Root Font Size" that is defined for the webpage. rem will return a multiple of the root font size. For example, if the root font size is 12px, 2rem with be 24px.

font-size: 1.2rem;

Percent

You can set an property to a size relative to the size of its parent element (that is, the tag that it is inside of). So, height: 100% will be the same height as the parent element.

height: 100%;

Viewport

You can set a property to have a size relative to the size of the current view, either the width or the height. For example, 90vh will be 90% if the height of the current visible area of the screen and 90vw will be 90% of the width of the current visible area of the screen.

height: 95vh;

Commonly Used Properties

There are a lot of properties that are used when styling with CSS. It is impossible to go through all of them within one book, let alone one chapter. So, we will review some of the most common and important ones. I highly recommend that you play with these with different values on your own so you can see how each one actually works.

Margin, Border, Padding, Height and Width

Since we are fresh off of the Box Model, we should first focus on how to change that content. We will start with the outside (margin), and move inwards.

Margin

As we discussed, margin is the space between each element. As with everything in the box model, there are four parts to them: the top, right, bottom, and left. Margins can be set for all sides at once, or individually.

1. margin: 2px;
2. margin-top: 2rem;
3. margin-right: 3rem;
4. margin-bottom: 4rem;
5. margin-left: 5rem;
6. margin: 2rem 3rem 4rem 5rem;
7. margin: 2rem 3rem;

The margin property can be set at once. In the first line above, it sets all margins to 2px around the entire element. You can also set the margins specifically using margin-[side] to define the margin on each side. In line 6, you can see that there are four values provided. When four values are provided, it will set the margins clockwise, starting from the top. So, lines 2-5 can be combined into one line, line 6. Lastly, you can set just the top and bottom and left and right separately. In line 7, when margin is given two values, the first value will set the top and bottom, and the second value will set the left and right margins.

Border

The border is the "last part" of the element before you exit it. As you saw in the Box Model, the border is everything between the margin and the padding. There are a lot of properties that customize the border, so lets jump right in.

border-top-width: 3px;
border-right-width: 4px;
border-bottom-width: 5px;
border-left-width: 6px;
border-width: 3px 4px 5px 6px;
border-style: dash;
border-color: red;
border-radius: 3px;
border: 1px solid red;

Generally speaking, the syntax for the border is border-[border side]-specific property. So, if you wanted to change the width of the border on the bottom, you would access border-bottom-width. As with margin, there is a shorthand way to set the border. The border property has three values: the width, style and color. So, border: 1px solid red will result in a border that is 1px wide, solid and red.

Table 2. Summary of Common Border Properties
Attribute Explanation Common Possible Values

width

Controls the actual width of the border.

It can be any value that controls unit size, but is typically px or rem.

color

Controls the color of the border.

Any type of color value.

style

The style of the border.

solid, dash, dotted

radius

This will add a radius to the corners of the border to make rounded corners.

Typically in pixels or rem.

Padding

Padding is the space between the content and the border. Setting the padding is analogous to margin, so we will not spend too much time on it. It is more important to visualize it.

padding: 2px;
padding-top: 2rem;
padding-right: 3rem;
padding-bottom: 4rem;
padding-left: 5rem;
padding: 2rem 3rem 4rem 5rem;
padding: 2rem 3rem;
Height and Width

We can also set the height and width of an element. We can do this using px or rem like this:

height: 100px;
width:3rem;

This is a way to fix the height and width. Or, we can use the %. This will create a value that is relative to its parent element. So, height:100% will take up the height of the entire parent element.

Display

We went over display earlier, but let’s look into it a little big more in depth. The three main values you should worry about now are block, inline, and inline-block. A block element will take up an entire row, and an inline element will just take up its own width. You can set the value of the property in one of the following ways:

display: inline;
display: block;
display: inline-block;

These are not the only values, but for the time being, they are the main ones we will deal with. As always, feel free to look up all of the other values and change the property values to experiment and see what happens.

Let’s say we have the following html code

<div class = "practice">
    This is just some practice text
</div>

Then, we add styling:

.practice{
    display: inline;
    height: 50px;
    background-color: black;
    color: white;
}

We will get an inline element with a black background and white text. However, if we were to set display:block, we would have a much different look. Height will not affect this element because inline elements only take up the size of the content. This is visualized below.

Display
Figure 16. Display

display is set to inline on the left side and block on the right side. The background color goes the length of the page and is 50px tall when it is block. When it is inline, it only is the height of the content.

What if you wanted an element to behave like an inline element, but be able to change the height? That is where inline-block comes in. Using the same CSS, but changing it to display: inline-block; will achieve this.

display: inline-block
Figure 17. display: inline-block

Now, it only takes up the width of the content, but now we can change the height property.

Lastly, you can change the CSS to display:none, and you will not see the content.

top, right, bottom and left

These value of these properties will depend on the position value. However, in general, the way these properties work is by putting a gap of the value you choose the property. For example, top: 5rem will shift the element down by 5rem because you are putting a gap of 5rem above the element.

Position

The position property helps determine where on the page an element is. Along with top, right, bottom and left, you can put an element wherever you want on a page. We will review these possible values, but it does not have nearly as much meaning until we learn other properties such as top and left.

Table 3. Summary of Common Position Values
Value Explanation top, bottom, left and right

static

By default, elements will have a default property value of static. An element with position: static will just be positioned relative to the normal flow of the webpage.

These will have no effect on static elements

fixed

Next, we can look at the position: fixed value. Wherever you end up putting an element, the element will be at the same position on the screen regardless of where you scroll.

These will position the element relative to the viewport. top: 95%; for example, will position the element 95% from the top of the viewport.

relative

This will have a position that is relative to its original position.

These will move the element relative to its normal position on the page. A value of left: 5rem will put a gap of 5rem to the left of the element.

absolute

This will have a position that will adjust itself relative to the nearest parent element.

These elements will be positioned relative to the nearest parent element.

Let’s look at what these position values look like in a webpage.

<html>
    <head>
        <title>My Webpage</title>
        <style type="text/css">
            div{
                border: 3px solid black;
                height: 5rem;
            }
            .div-static{
                position: static;
                top: 3rem;
            }
            .div-relative{
                position: relative;
                top: 3rem;
            }
            .div-absolute{
                position: absolute;
                top: 1rem;
            }
            .div-fixed{
                position: absolute;
                top: 80%;
            }
        </style>
    </head>
    <body>
        <div class="div-static">
            This content is static.
        </div>
        <div class = "div-relative">
                This is content relative.
            <div class="div-absolute">
                This is content absolute.
            </div>
        </div>
        <div class = "div-fixed">
            This content is fixed.
        </div>
    </body>
</html>

The code results in the following:

Positioning
Figure 18. Positioning

The static content is first and is just in the normal flow of the page. The top value has no effect on it.

The relative content is relative to its normal position. It should have come right after the static content. However, there is now a gap of 3rem, which shifts the content down 3rem.

The absolute content will shift relative to the nearest position: relative parent. So, it is shifted down 3rem relative to the top of the div-relative. You can confirm the relative and absolute behavior by looking at the gap between the bottom of the static content and the top of the relative content, then the top of the relative content to the top of the absolute content. The lengths are both 3rem.

Finally, the fixed content is fixed at 80% of the viewport. It will always stay there and has a gap of 80% of the viewport height above it.

Float

The float property is a great way to position content. It specifics where to place the content within its container. It takes the values left, right, inherit and none.

Generally speaking, you should always use position: relative when using float, because it is a property that will position something relative to the parent. Let’s say we have the following html:

<div class="parent">
    <div class="right-content">
        Right Content
    </div>
    <div class="left-content">
        Left Content
    </div>
</div>

Normally, you would see the right content come before the left content. However, let’s add the following CSS:

.right-content{
    float: right;
}
.left-content{
    float: left;
}

Now, the right content will go to the right and the left content will go to the left.

Float
Figure 19. The left browser does not have the float properties set, the right one has them set with the preceding code

Fonts

There are a few ways to adjust the font of a page. Let’s first focus on font-size. We can use any of the units to define this.

font-size:1rem;

or

font-size:10px;

These will change the size of the font to 1rem or 10px respectively.

We can also change the actual font of the element, using font-family. Google Fonts is great for this, and will actually walk you through how to use it. For example, go to Google Fonts. Search for the "Roboto" font. Click on the "+".

This will give you what you need to define in your webpage. First, you will need a stylesheet, which is provided in Google Fonts.

<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">

This is the stylesheet for the "Roboto" font. You can put this in the <head> along with the rest of your stylesheets. Then, you can copy and paste the font-family property from Google Fonts.

font-family: 'Roboto', sans-serif;

Now, we are good to go. This specifies the font that will be used for the element.

Color

When you want to change the color of an element, you can change the background color or the font color. You can use two different properties to change the color of these parts of an html element.

First, you can change the background color of the element. In order to do that, you use (guess what!) the background-color property.

background-color: rgb(154, 234, 122);

The background-color property will change the background of the element up to the borders - that means the content itself and the padding.

You can also change the color of the font using the color property.

For example, the following code will create a class with white text and black background.

.black-white{
    background-color: black;
    color: white;
}

Remember: color will change the color of the content and background-color will change the background color.

Text Align

Most of the time, you want to be able to align your content in a certain way. This is where the text-align property comes into play.

text-align helps do exactly what is sounds like. It will help align text within an element.

Let’s say we have the following html code:

<div class="text-align">
    Center Text
</div>

And let’s say class text-align has the following CSS.

.text-align{
    border: 2px solid black;
    display: block;
    text-align: center;
}

We know that the element will span the entire width of the browser because of display: block;. The content "Center Text" will be in the center of element which will be in the center of the browser.

What happens when we change display to inline? It will only take up the room of its content, so it will stay on the left side of the browser. The following figure shows what happens to the div with class="text-align" with display: block on the left and display: inline on the right.

`text-align`
Figure 20. text-align

However, if we changed the padding of the inline element, the content would be centered within the padding, per the box model. Let’s change the CSS:

.text-align{
    border: 2px solid black;
    display:inline;
    text-align:center;
    top: 3rem;
    position: relative;
    padding: 2rem;
}

We added the position and top properties just so you could see the top border clearly in the browser. Now, we get the following:

Inline with padding
Figure 21. Inline with padding

text-align can also have values of left, right and justify.

Tip
It is common to set text-align: center for parent elements so that all of the elements within are centered.

Responsive Design and Bootstrap

Responsive Design is an integral part to modern web design. Responsive Design refers to a design philosophy that allows a website or web app to look great on screens of all sizes. Before mobile devices, this was not much of a consideration. However, as time has gone on, mobile devices and other devices that do not have the same screen size/proportions as normal desktops/laptops have become more and more common. It is therefore extremely important to create websites that are responsive - that is, responds to changes in the size of the screen. Let’s look at an example.

W3Schools.com implements responsive design. On a normal screen, the website looks like this:

Desktop View W3 Schools
Figure 22. Desktop View W3 Schools

This is no surprise - it has been seen before. However, when we look at it on a mobile device, it looks like this:

Mobile View W3 Schools
Figure 23. Mobile View W3 Schools

The mobile view is much different than the desktop view: the content becomes stacked on top of each other so it can be easily viewable in the width of the screen. In addition, the navbar has collapsed, to be expanded when you click the three bars at the top of the screen. This is a common responsive design tactic for the navbar. We will go into media queries and then learn Bootstrap, a front end framework developed by Twitter that makes responsive design very easy to implement.

Media Queries

A media query is how you can set different styles based on different screen sizes. In your CSS, you will define all of your styles. Then, you will create media queries which specify the styles you want in different screen sizes. So, let’s say we have the following code:

<html>
    <head>
        <style type = "text/css">
            .responsive-class{
                background-color:yellow;
            }
        </style>
    <head>
    <body>
        <div class = "responsive-class">
            This content is within a responsive class.
        </div>
    </body>
</html>

It should not surprise you that it will look like the following in the browser:

Responsive Design - Desktop View
Figure 24. Responsive Design - Desktop View

Our webpage will look like this regardless of the size without any media queries. However, let’s change the code in the <style> tag to the following:

<style>
    .responsive-class{
        background-color: yellow;
    }
    @media (max-width: 500px){
        .responsive-class{
            background-color: red;
        }
    }
</style>
Responsive Design Under 500px
Figure 25. Responsive Design Under 500px

The image above shows what the webpage will look like given this style. What this does is set a style on screens with a maximum width of 500px. If it is more than 500px, .responsive-class' will have a `background-color: yellow;. This is the premise of responsive design: you will set media queries for all your classes and ids so they know how to behave on different screen sizes. You could put any styles in the media query and also change the max-width property to max-height, min-width and min-height. There are many other ways to set media queries, and there are plenty of resources that list these ways out. Thanks to many different tools on the internet, responsive design can be done much more efficiently than constantly making media queries. Bootstrap, for example, is a library that does much of this for you. We will jump into it now.

Bootstrap

Bootstrap is a front end framework/library that allows you to easily create mobile-friendly websites. Not only is it great for mobile websites, but it has a lot of handy helper features that make styling very easy. Bootstrap makes it very easy to get it in your webpage. In your <head>, simply add the following link:

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">

Then, at the end of your <body>, add the following:

<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>

This is all you need to get Bootstrap started. Bootstrap is just a stylesheet and Javascript scripts that you can use. For future reference, you can get your Bootstrap links here.

One of Bootstrap’s main features is its grid system. The grid system organizes the HTML in a way that will change the layout when it goes to certain screen sizes. As we are going through this chapter, try adjusting the size of your screen to different heights and widths to understand how the style changes.

Grid

Bootstrap first starts by using containers. Containers are used to help organize your html when you are organizing it. Within containers, you have rows and columns that you organize your code in.

Containers

Bootstrap has two types of containers - container and container-fluid. A container will have a width that is responsive to the size of the screen and will not take up the entire width. A container-fluid element, on the other hand, will have a width of 100% - meaning it will take up the entire width of its parent element. These are classes that are assigned to html elements. So, to implement them, you would use the following.

<div class = "container" style = "background-color: blue;">
    This is my container.
</div>

<div class = "container-fluid" style = "background-color: red;">
    This is my container-fluid.
</div>
Containers
Figure 26. Containers

As you can see, the container will not have the same width as container-fluid. The container class will change its width depending on the size of the screen, whereas container-fluid will always have width: 100%. You will typically apply these classes to <div> elements.

Rows

Within a container, you will have multiple rows. This is how Bootstrap arranges content - rows within a container.

It is defined as the following:

<div class = "container">
    <div class = "row">
        CONTENT GOES HERE
    </div>
</div>
Columns

Bootstrap’s columns is where the magic really happens. Within each row, there are twelve potential columns. However, there can be anywhere between 1-12 columns per row. It is segmented by 1, and you will want the class of your columns to add up to 12. This does not mean a lot without looking at it more.

Let’s say we have content that we want to be split into two columns of equal width on a page. We can simply will type the following:

<div class = "container">
    <div class = "row">
        <div class = "col-6">
            This is "col-6"
        </div>
        <div class = "col-6">
            This is the second "col-6"
        </div>
    </div>
</div>

Which will result in the following:

Columns
Figure 27. Columns

The two columns will take up 6 of the 12 sections that Bootstrap divides rows up into. That means that each column will take up half of the screen. We could also do the following:

<div class = "container">
    <div class = "row">
        <div class = "col-4">
            This is "col-4"
        </div>
        <div class = "col-4">
            This is the second "col-4"
        </div>
        <div class = "col-4">
            This is the third "col-4"
        </div>
    </div>
</div>

This would look like this:

Three Columns
Figure 28. Three Columns

Each of these columns will take up one third of the page. This makes it easy for responsive pages, as the actual width of the columns will change based on the size of the screen.

However, Bootstrap makes it even better. What if our screen gets too skinny? Our columns will get very squished and we would potentially see one word per line per column, like the following:

Skinny Screen
Figure 29. Skinny Screen

Bootstrap sets up media queries to take care of this. They have set four different screen sizes: xs, sm, md, and lg. These screen sizes correspond to different breakpoints.

Table 4. Summary of Bootstrap Breakpoints
Label Breakpoint

sm

Greater than or equal to 576px

md

Greater than or equal to 768px

lg

Greater than or equal to 992px

xl

Greater than 1200px

So, the way these work is to implement them in the col- classes. The syntax would be col-[breakpoint]-[number]. Let’s jump right into an example.

<div class = "container">
    <div class = "row">
        <div class = "col-sm-3">
            This is "col-sm-3"
        </div>
        <div class = "col-sm-3">
            This is the second "col-sm-3"
        </div>
        <div class = "col-sm-3">
            This is the third "col-sm-3"
        </div>
        <div class = "col-sm-3">
            This is the fourth "col-sm-3"
        </div>
    </div>
</div>

This will create breakpoints at 576 pixels. What the html classes are saying is that when the width of screen is at 576 pixels or more, the columns will stay next to each other. However once it goes below, the content will stack on top of each other.

Over 576px on left
Figure 30. Over 576px on left, under 576px on right

You can do the same with the md, lg, and xl with a variety of columns. We can also apply multiple breakpoints. Let’s say we have four col-3 in a row. When we get to a certain point, we want two rows of col-6 and when it gets smaller, then we want it to be four rows. This will be done using the following code:

<div class = "container">
    <div class = "row">
        <div class = "col-md-3 col-sm-6">
            This is "col-sm-3"
        </div>
        <div class = "col-md-3 col-sm-6">
            This is the second "col-sm-3"
        </div>
        <div class = "col-md-3 col-sm-6">
            This is the third "col-sm-3"
        </div>
        <div class = "col-md-3 col-sm-6">
            This is the fourth "col-sm-3"
        </div>
    </div>
</div>

It tells the columns how to behave in different breakpoints. So, first it will abide by the col-md-3 behavior, then it will abide by the col-sm-6 behavior. Our webpage will look like the following:

Before it hits md:

Greater than `768px`
Figure 31. Greater than 768px

Before it hits sm:

Greater than `576px`
Figure 32. Greater than 576px

Before it goes below sm:

Less than `576px`
Figure 33. Less than 576px

Now that we have learned how the Bootstrap grid works, let’s look at some other Bootstrap features.

Other Features

Bootstrap is great for responsive design for the entire layout of the page. It also has a few other utilities that make it useful.

Navbar

The Bootstrap Navbar is one of the best features, in my opinion. It creates a navigation bar that collapses when it gets to a certain breakpoint. So, it will look like a normal navigation bar at the top of the screen until it hits a certain point. Then, it will collapse the actual navigation links and show a button that you can click to reveal the navigation links. Bootstrap has great documentation, so whenever I need a component, such as a navbar, I will start off with the code they have in an example, and then change it accordingly. Using the Navbar from Bootstrap’s documentation, we can start with the following code.

<nav class="navbar navbar-expand-lg navbar-light bg-light">
    <a class="navbar-brand" href="#">Navbar</a>
    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
    </button>

    <div class="collapse navbar-collapse" id="navbarSupportedContent">
        <ul class="navbar-nav mr-auto">
        <li class="nav-item">
            <a class="nav-link" href="#">Home</a>
        </li>
        <li class="nav-item">
            <a class="nav-link" href="#">Link</a>
        </li>
    </div>
</nav>

In a screen that is 992px and larger, it will look like this:

Greater than or equal to `992px`
Figure 34. Greater than or equal to 992px

And smaller screens, such as mobile, will look like this:

Less than `992px`
Figure 35. Less than 992px

Their default Navbar in the first example code is much more complex, with many different item types. However, let’s start with the previous code.

We first have our entire <nav> tag that will be the parent. The class=navbar-expand-lg will determine when the navbar collapses, which is the 992px breakpoint. Then, we have our first link with class="navbar-brand". This is where you would put the title of your page, let’s say, or maybe a logo.

Then, you have a button with class="navbar-toggler". This is what shows up when your screen is under 992px.

We can now go to the links of the navbar, <div class = "collapse navbar-collapse">. This is the part of the navbar that will collapse. Within this, we have our class="navbar-nav" which is where all of the links are.

Those are the basics of navbars. You can look at the documentation for all of different types of links for navs.

Common CSS Classes

Bootstrap has a lot of helper functions that assist with common CSS styling. These include padding, margins, display and position, among others.

Generally speaking, there is a very simple pattern to apply certain styles to a tag. They will start with a prefix:

  1. padding: p

  2. margin: m

  3. display: d

  4. position: position

Padding and Margin

Let’s look at padding and margin. After the first letter, you will have another letter or a -.

  1. -: all

  2. t: top

  3. b: bottom

  4. l: left

  5. r: right

This shows where you will put the padding or margin. Then, you will put an integer between 0 and 5, or auto to determine how much margin or padding. These integers will increase the amount of padding or margin, based on Bootstrap’s own calculations that you can change with Sass. So, let’s look at a few examples.

  1. pt-1: padding-top

  2. mb-3: margin-bottom.

  3. p-2: padding

The integers, once again, are determined by Bootstrap, but can be changed. For beginners, you can just use these classes to have a general increase or decrease in padding/margins, but you will not be able to be very specific.

Display

We first use d to set a class for display, then we put one of the values for display, such as inline or inline-block.

  1. d-inline: display: inline

  2. d-none: display: none

We can also mix in some break points, such as d-md-none, which will give the element a display: none value below the md breakpoint.

Position

Position is easy. All you need is the position- prefix, and then type the value you want. The following will give the <div> the style position: absolute.

<div class = "position-absolute">
</div>

Bootstrap has many, many great features, and we barely covered them in this chapter. I suggest to read the documentation more and use it when you can see the functionality of it. When we start creating a Django project, we will implement these features on the front end.

Python

Python is a programming language that was invented for readability. It should read very close to English, especially relative to other progamming languages. Python also has a lot of things that are built in that make it ready to go.

Console vs script

First, we will be using two terms: console and script throughout this book. A console is an interactive way to create Python code. This allows you to code in real time and see the results.

A script, on the other hand, is a collection of statements that are executed in one swoop. It is typically saved in its own file (or files) as a .py (or Python file)

First, let’s install Python. Go to the following: https://www.anaconda.com/distribution/ Download the Python 3.7 version. When you download the package, you should be able to follow the instructions to install.

If you want to use a Javascript console, simply open Google Chrome. Then, right click and click "inspect". A window will open at the bottom of the screen and there will be a bar along the top of that window. Look for "console" and click it. If you want to use the console, this is the best way to use it while going through this chapter. This chapter will typically be more beneficial if you use the console, and the following chapters will focus on separate scripts and .js files.

Variables and Built In Functions

What is a variable? In simplest terms, a variable is a piece of information that is stored. This piece of information can be anything from a letter to a number. In Python, you do not need to specify the variable type or even specify that it is a variable when you create it. The general syntax is below.

_name_ = value

If you want to create a variable that holds your first name, you could do the following:

my_first_name = 'Tanner'

Now, whenever you refer to my_first_name, it will refer to the value 'Tanner'.

Boolean

A boolean is a variable that can hold one of two values: True or False. These two values are keywords in Python, so it will automatically recognize the value as a boolean if you type it correctly.

i_like_the_rams = True

In this example, I set the variable i_like_the_rams to True. As we will learn later in this chapter, booleans are helpful to conditionally perform tasks. For example, if I am an online retailer, and I save whether or not somebody is a Rams fan, I can then push notifications for Rams products if i_like_the_rams = True for a given customer. There are obviously better ways to do this, but this is just to help explain.

String

A string is a collection of letters. This can be one letter or multiple. In order to create a string, you use quotations. This can be double ("") or single (''). A few examples are below.

first_name = 'John'
last_name = 'Smith'
favorite_movie = "A Few Good Men"

Generally speaking, when you define a variable in Python, you lowercase all letters and use _, as a matter of convention.

If you want to combine strings, you can use the + sign to concatenate. So, I could do the following:

my_full_name = first_name + " " + last_name

This will result in John Smith. We put a space between them using normal quotes and a space to show that you don’t need to necessarily save the content in another variable when concatenating them.

Int

An int is a variable that holds the variable of an integer. An integer is just a whole number. An example would be 3 or 18273.

In order to create an integer, you can do the following

three = 3
four = 4
one_hundred_four = 104

We can do mathematical operations with integers by using the operations you already know: addition (+), subtraction (-), multiplication ('*'), and division ('/'). There is also the modulus operator (%), which will return the remainder of the division of two numbers.

Modulus Operator
3 % 2
>> 1
23 % 5
>> 3

Does this make sense? If you divided 3 by 2, the remainder would be 1. If you divided 18 by 5, the answer would be 3, remainder 3.

The last main operator is the exponential operator, (**).

3**2
>> 9
8**3
>> 512

Float

A float is simply a number that has values in the decimal places. So, 3.4 is a float, but not an int. 3 is an int, but not necessarily a float. On the other hand, 3.0 would necessarily be a float because there is a value after the decimal places, even if that value is 0.

All of the operators work on floats, other than the modulus operator. By definition, the modulus operator only works on integers.

Built In Data Types

After just pure variables, Python has a variety of Data Types that hold more than one piece of data. Their properties and behavior vary, but they are very useful for performing calculations and dealing with data. We will try to go through all of the data sets, but we don’t want to just repeat the common items that are already in the Python docs. For further reference, go to the following link look at more details of the built in Data Types: https://docs.python.org/3/tutorial/datastructures.html

Sets

A set in python is a group of items that are created with Set([set items]) or {set items}. A set can have a collection of any data type, including a set of sets. Let’s look at the following code.

my_set = {1,2,3}
my_other_set = Set([1,2,3])

The two sets above are identical. We can check this in a console.

my_set == my_other_set
>> True

If you want to check if a certain element is in a set, you can use in or not in

1 in my_set
>> True
8 in my_set
>> False

These are only some of the common operations. Feel free to look up the Python docs to look at all of the possible operations for comparing Sets.

Tuples

A tuple is a collection of ordered data that can be referenced by the index. The index is the location in the Tuple that your piece of information is located, and the index starts at 0. This is very important: THE INDEX STARTS AT ZERO.

Let’s define a tuple

my_tuple_1 = (1, 2, 3, 4)
my_tuple_2 = 1, 2, 3, 4

Both of these methods will create a tuple with the values provided. If we wanted to access the element with value 1, we would use the following notation:

my_tuple_1[0]

The braces signify that we are going to look for the value with index = 0 in my_tuple_1. We will review indexing more in depth after we review lists in the next section.

Lists

Lists are one of the most widely used built in data types in Python. A list is a mutable, ordered list of items that can be of any data type. For example, you can have the following valid lists:

my_list_1 = [1, 2, 3, 4]
my_list_2 = ["Alan", "Bob", "Chris", "Dan"]
my_list_3 = [1, "Bob", 3, 4]

Remember that indexing starts at zero. So, if we wanted to access "Alan" in my_list_2, we would use my_list_2[0].

We can also change elements in a list like the following:

my_list_1[0] = 100
print(my_list)
>> [100, 2, 3, 4]

Let’s now look at some common methods used with lists. First, is the append() method.

If you want to add an element to the end of the list, simply type the following:

my_list_1.append(10)
print(my_list)
>> [100, 2, 3, 4, 10]

Let’s say we want to put an element somewhere else in the list. We want to put a value of 12 between 4 and 10.

my_list_1.insert(4, 12)

This will add the value of 12 in index 4, and shift the rest of the elements.

What about removing elements? We can use pop(). Without an argument, it will remove the last element of the list. If there is an argument, it will remove the element at the index you specify.

This will remove the last element of the list:

my_list_1.pop()

This will remove the second element of the list:

my_list_1.pop(1)

Now that we have gone through some data structures, let’s look how to use indexing to really understand how to manipulate the data.

Indexing

Indexing is a very important way to access information in a data structure. Specifically, we will be looking at lists, because indexing requires the data structure to be ordered.

So, if we want to get the first element (not the element with an index = 1, but the first element in the list), we simply type my_list[0]. This will return the first element. However, what if we want to return the last element. Well, index = 0 gives you the first element and index = 1 gives you the second element, we can get the last element by getting the length of the list and subtracting one. So,

my_list = [1,2,3,4]
my_list[len(my_list) - 1]
>> 4

This seems a little bulky, so there must be a better way. Well, we can use negative indices. So, we could also do the following:

my_list[-1]
>> 4

This works because it will "wrap around" to the end of the list. If we you wanted to get the second to last item, you would use my_list[-2].

What if we wanted to slice a list and get certain sections of one? We can use the : when indexing. So, let’s say we have a new list:

my_list = [0,1,2,3,4,5,6,7,8,9]

Let’s look at a few ways that we can use indexing to split this list up

my_list[0:5]
>> [0, 1, 2, 3, 4]
my_list[:5]
>> [0, 1, 2, 3, 4]
my_list[1:]
>> [1, 2, 3, 4, 5, 6, 7, 8, 9]
my_list[:]
>> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
my_list[:-1]
>> [0, 1, 2, 3, 4, 5, 6, 7, 8]

Note that if you are slicing using two numbers, that is like my_list[0:5], it includes the value in the first referenced element and excludes the value in the last element you send it. So, it will not return the value of my_list[5] in that instance.

Dicts

A dict is a very powerful data type in Python that you will come across often and is frequently used in Django. It is a type of hash map that is built in Python. However, we can review dicts now.

A dict saves multiple pieces of data using key, value pairs. It is similar to a JSON object in that way. Let’s look how to create one:

my_dict = {
    'key_1': 'value_1',
    'key_2': 'value_2'
}

There are two entries in my_dict. The first one has a key of 'key_1' with a value of 'value_1'. The second has a key of 'key_2' with a value of 'value_2'.

In order to access the values, we use the syntax:

my_dict['key_1']
>> 'value_1'

We can change the values in a dict by doing the following:

my_dict['key_1'] = 'new_value'
my_dict['key_1']
>> 'new_value'

The entries for the keys must be strings. The values in the dict can be of nearly any data type. So, you could do the following, for example:

my_other_dict = {
    'key_1': [0,1,2],
    'key_2': 88
}

Remember: when you access either 'key_1' or 'key_2', it will return whatever the value is. So, if we wanted to get the second element in the list for 'key_1', we do the following:

my_other_dict['key_1'][1]
>> 1

It is that easy. We will learn more about using dicts when we look at loops, so we can learn how to cycle through the information in a dict.

Summary of Common Data Types

Table 5. Summary of Common Data Types
Name Syntax Mutable Ordered

Set

{} or Set([])

Yes

No

Tuple

() or just list out the data with commas

No

Yes

List

[] or list([])

Yes

Yes

Dict

{'key': value}, or dict()

Yes

N/A

Converting Between Variables

Python has built in functions (we will cover custom functions later) that help work between ints, floats and strings. If you want to convert a variable to an int, you would use the int() method. For floats, you use the float() method and for strings, you use the str() method. When would this come up in programming? Let’s look at an example.

Calculating from Console

Python has a function called input() that saves the input from a user in the console. By default, Python saves this value as a string. However, we want to perform calculations. So, we can convert these values into a float in order to perform calculations. We want our code to do the following in the console:

Please input your first number: 3
Please input your second number: 4
The sum of these is 7

First, we need to save the value as a variable.

num_1 = input("Please input your first number: ")
num_2 = input("Please input your second number: ")

This is the syntax that is used in the source code. It will put the text in the input function in the console, and will take the input right after. So, per the console code, num_1 = 3 and num_2 = 4.

We continue our code.

num_1 = float(num_1)
num_2 = float(num_2)
sum = num_1 + num_ 2

Now, we have 7 saved as a value in sum. We need to output the answer, however. This is using the print() function. The print() function takes in as many arguments as you want, and outputs them in the console. We could do the following

print("The sum of these is ", sum)

This function will automatically output the number. However, what if we wanted to just combine the output in one string? We could do the following:

print("The sum of these is " + str(sum))

Both of these methods would output the same to the console. To wrap it up, this is what our entire script would look like.

num_1 = input("Please input your first number: ")
num_2 = input("Please input your second number: ")
num_1 = float(num_1)
num_2 = float(num_2)
sum = num_1 + num_ 2
print("The sum of these is " + str(sum))

Logic and Loops

Much of programming revolves around checking for different conditions and performing tasks conditionally and repetitively. This section will focus on implementing logic and loops in Python.

Logic

First, let’s take a look at if statements. An if statement will create a set of conditions that will create different code blocks to execute, depending on which condition is true.

if 5 + 5 == 1:
    print("5 + 5 = 1")
elif 5 + 5 < 9:
    print("5 + 5 < 9")
else:
    print("5 + 5 = 10")

Let’s first look at the syntax. In Python, if statements are defined by using the keyword if like many other languages. After the if keyword, you put the first condition followed by a colon. If this condition is True, the code that is indented underneath the first condition is executed. Note that there are no braces - Python uses white space to its advantage. All of the logic within an if statement must have consistent white space in each line.

If the first condition is False, it will go to the next condition. In this case, it is the elif keyword. This means "else if". It will then look at this condition to see if it is satisfied. As with the first condition, if it is true, it will execute the code in the block, which means it will print to the console ("5 + 5 < 9"). We know this is False, so it will go to the next condition.

The next condition begins with else with no logic. This is because this is the "last line of defense". It will go to see if each condition is True or False. If all of the preceding conditions are False, it will execute whatever is in the else block.

It is important to remember that all if statements must have at least one if keyword. The elif and else conditions are not necessary. If there is an if statement with no else, then nothing will execute. For example,

if 5 + 5 == 9:
    print("This condition is True")

In this case, if this were all that was in your code, nothing would print to the console. It is valid code, it just would not do anything visible.

If statements will execute the code beneath it if and only if the condition is True

You may have noticed that if statements have comparisons in their conditions. The following table shows the different ways to compare variables.

Table 6. Summary of Comparison Operators
Syntax What it Does Example

==

Checks to see if two objects are equal

3 == 3 will be True. 3 == 6 will be 'False'.

>

Checks to see if one element is greater than another

10 > 4 will be True. 4 > 10 will be False.

>=

Checks to see if one element is greater than or equal to another.

'15 >= 15' will be True. 15 > 15 will be False.

<

Checks to see if one element is less than another.

15 < 4 will be False. 4 < 15 will be True.

Checks to see if one element is less than or equal to another.

'3 ⇐ 3' will be True. 3 < 3 will be False.

!=

Checks if two objects are not equal

5 != 5 will be False. 5 != 6 will be True

is

Checks to see if two things are the same Object.

5 is 5 is True. 5 is 5.0 is False.

is not

Checks to see if two things are not the same Object.

5 is not 5 is False. 5 is not 5.0 is True.

in

Checks to see if a certain element is in a group of other elements (a set or a list, for example)

"Hello" in ["Hello", "World"] is True

not in

Checks to see if a certain element is not in a group of other elements (a set or a list, for example)

"Hello" not in ["Hello", "World"] is False

and

Checks to see if two conditions are True or False. Will return True if and only if both are True.

3 == 3 and 4 == 4 will return True

or

Checks to see if two conditions are True or False. Will return True if one of the conditions are True.

3 == 3 or 4 == 5 will return True

Use this table as a reference when you are trying to compare different values in if statements or other parts of your code.

Loops

A loop is a feature in programming languages that allows you to perform repetitive tasks. A loop is a feature in programming languages that allows you to perform repetitive tasks. A loop is a feature in programming languages that allows you to perform repetitive tasks. A loop is a feature in programming languages that allows you to perform repetitive tasks.

In case you didn’t know, a loop allows you to perform the same task over and over. In Python, there are two types of loops: while loops and for loops.

While Loops

A while loop is called a 'while loop' because it will perform iterations of while a certain condition is true. It will first look at the condition, then determine if the condition is True. If it is, it will go through the list of directions you are asking it to perform. The directions will need to be indented by a consistent number of spaces below the while statement. The general syntax is below:

while some_condition_is_true:
    # do something

This is great and all, but what is it relevant for? Let’s jump into an example. What if we want to print all numbers between (and including) 1 and 100? We could just use the print() function for each number and have 100 lines of code. But, that is inefficient. So, we could do the following:

output = 1
while output <= 100:
    print(output)
    output = output + 1

So, instead of typing 100 lines of code, we can type 4.

For Loops

A for loop is another loop structure. However, it typically is used to iterate through something. The general syntax is as follows:

for some_iteration:
    # do something

So, let’s say we define a list:

my_list = [0, 1, 2, 3, 4, 5, 6]

We want to print out something like "The number is: x", and continue that for each value. We could use a for loop:

for value in my_list:
    print("The number is: ", value)

This will loop through the values in my_list. You could name value anything - that is up to you. It just needs to remain consistent with how you reference it in the actual loop logic.

Let’s say we want to be able to access the index. We can only access the value in this instance. Well, we can use the enumerate() function. This will give us a counter to go along with the value.

for index, value in enumerate(my_list):
    print("The number in index {} is {}".format(index, value))

We send in two variables, and it will loop through the list while giving us access to both the index and the value.

We also will want to iterate through a dict sometimes. There is a handy method for dicts called items(). This will do something similar to enumerate(), but will give the key and the value instead of the index and the value. For example:

my_dict = {
    'key_1': 1,
    'key_2': 2,
    'key_3': 3,
    'key_4': 4
}
for key, value in my_dict.items():
    print("Key: {}, Value: {}".format(key, value))

This will print out the following:

Key: key_1, Value: 1
Key: key_2, Value: 2
Key: key_3, Value: 3
Key: key_4, Value: 4

We would then have access to both the key and value in this case.

Functions

We have looked at some of the built in functions in Python, such as print(). However, in programming languages, you can create your own custom functions. Functions are great for snippets of code that you will need to reuse, or just to clean up your code.

How do we create our own function in Python? We start using the def keyword. This keyword lets Python know that we are creating a function. Then, we follow it with the name of the function and any arguments that we are going to send.

def my_function(num_1, num_2):
    #your code goes here

The preceding code shows a generic definition for any function. "my_function" is the name of the function, and it receives two arguments, num_1 and num_2. Then, within the block of the function, you indent and put your code. All lines of code must be indented the same in Python, because it uses whitespace instead of brackets, like in Javascript.

In Python, functions can return a value. That means, that we can put our inputs in the function, and we want some sort of output. We do this using the return keyword.

def my_function(num_1, num_2):
    #your code goes here
    return some_value

In this case, the function will execute all the code, and then return a value.

In order to call a function, you simply type the name of the function in your console or script. So, let’s look at an example.

def addition(num_1, num_2):
    sum = num_1 + num_2
    print(sum)

In our console:

addition(3, 4)
>> 7

This function will simply print the sum to the console. However, what if we wanted to save the value of the sum? We would have to return a value. So, we would make our function look like the following:

def addition(num_1, num_2):
    sum = num_1 + num_2
    return sum

In our console: my_sum = addition(num_1, num_2): print(my_sum) >> 7

Now, we can refer to our sum whenever we want.

Our function must have two arguments, otherwise it will not work, and there will be an error.

my_sum = addition(1)

Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: addition() missing 1 required positional argument: 'num_2'

Python throws back a TypeError saying that it is missing an argument. So, we can change our addition function to the following:

def addition(num_1 = 0, num_2 = 0):
    sum = num_1 + num_2
    return sum

If you put default values in the arguments when you are defining a function, it will use these values if no other value is provided. I chose 0 arbitrarily, and any value can be chosen in reality.

Now:

my_sum = addition(1)
print(a)
>> 1

This is because it will take the first number we input, 1, as the first argument, num_1, and if there is no second argument provided, the value of num_2 would be 0.

Factorial Example

Let’s put everything we have learned so far to use. We are going to make a simple function, called factorial, that takes in a number. Factorial will return the factorial of the number that is sent to the function.

Note
A factorial, denoted with an exclamation point, returns the product of all of the numbers less than and including the number, but not zero. For example, 3! = 3 * 2 * 1 = 6. 0!, however is 1 by definition.

Before reading along, I suggest trying it yourself. First, we know that we will have to define a function, called factorial. It will return the final product. We can start like this:

def factorial(number):
    product = number
    number = number - 1
    _#logic will go here._
    return product

So far so good. The reason we defined product as number will make sense soon. Next, we will need to decrease the number by one until it reaches 1. This sounds like the perfect time for a loop. I suggest a while loop. So, let’s start

while number > 0:
    product = product * number
    number = number - 1

Since we defined our product as number, then subtracted one, the first line will multiply our product by our number - 1. After this, we will decrease number by 1. We will keep doing this while number > 0. That means this will stop at 1. We will then return our product.

A couple things, however. We need to make sure we are getting an integer as an input. A quick, easy way to do this would be to transform the number into an integer, rather that doing a bunch of validations. In the first line of your function, you can put:

number = int(number)

One last thing. We need to make sure that if we are given 0, it returns 1, by definition of a factorial. We can add a quick if statement after we transform the number into an int.

if number == 0:
    return 1

Now, let’s put it all together.

def factorial(number):
    number = int(number)
    if number == 0:
        return 1
    product = number
    number = number - 1
    while number > 0:
        product = product * number
        number = number - 1
    return product

That’s it! You just made a python function.

Recursion

It is easy to implement the factorial function using a loop. However, we can also use a feature called recursion. Recursion is when we call a function within itself. It sounds confusing, but it is pretty straightforward.

Let’s look at a non-recursive example, where we want to make a function that prints out every number from our number, down to zero.

def count(number):
    while number >= 0:
        print(number)
        number = number - 1

This function will simply print every number from number down to zero. However, when dealing with repetition in functions, you can consider to use recursion. We would change the count function to the following:

def count(number):
    print(number)
    if number != 0:
        return count(number - 1)

Do you see how this works? Python allows us to call the function within the function itself. It will print the number, and if it is not 0, it will perform the count function for the next number.

It doesn’t look like there is a great difference between the two methods in this example. Let’s look at the previous example of a factorial using recursion.

Recursive Factorial

We will start off with the same function definition, because it will still get a number as an input. Then, we will do the same as we did before, where we changed the number to an int, in case the use input a float. The case of number=0 is the same as the previous example.

So far, we have the same;

def factorial(number):
    number = int(number)
    if number == 0:
        return 1

Now we have to figure out how to recursively use the same function. We know that 4! = 4 * 3 * 2 * 1. This is the same as saying 4! = 4 * 3! = 4 * 3 * 2!. Now we are getting somewhere. We can see that each factorial function depends on a factorial of the next number. If we want to write it in more computer science form, it would be: factorial(4) = 4 * factorial(3), and so on.

So, if number != 0, we should multiply the number by the factorial of the number below. Our new function should look like this:

def factorial(number):
    number = int(number)
    if number == 0:
        return 1
    else:
        return number * factorial(number-1)

Recursion will likely take some practice to truly understand, and how to implement it. However, we can see that in this example, it shortens the factorial function code by nearly half.

args and kwargs

A great feature in Python and other programming languages is the keyword *args and *kwargs. These two allow you to pass any arbitrary amount of arguments to a function without having to explicitly define them in the function definition.

As always, let’s look at an example:

def addition(num_1, num_2, num_3):
    return num_1 + num_2 + num_3

In this example, we want to create a function that takes in a max of three numbers and returns the sum. But what happens if we want to only send two numbers? Then, we have to make sure they are all defaulted to zero, in case there are less arguments passed to the function. What if we want to send in more than three numbers? We would need to change the arguments to have a num_4.

Or, we can use *args. This allows us to send in as many arguments as we want. So, let’s change the addition method to include this.

def addition(*args):
    sum = 0
    for i in args:
        sum += i
    return sum

*args is of type tuple, so you can loop through it. Now, you can send in any amount of numbers and this will return the sum. In the console:

print(addition(3,2,7,3,4))
>> 19

The * tells Python that you are sending in the *args argument.

Now, let’s move onto kwargs. kwargs is similar to *args, but instead of sending a tuple, it sends a dict. Let’s say we wanted to create a function that returns a formatted version of a letter. So, we have a template:

Dear [blank],

My name is [blank]. I want to talk to you about [blank].

[More content goes here].

Sincerely,
[blank]

In this case, we have a very simple template that will have a few different inputs. Inputs (arguments) are

  1. Addressee

  2. Author

  3. Subject

  4. Other content

We could create the function by doing the following:

def letter(addressee = "", author = "", subject = "", other_content = ""):
    output = "Dear {},\n My name is {}. I want to talk to you about {}.\n{}\n Sincerely, \n{}".format(addressee, author, subject, other_content, author)
    return output

This is a cumbersome way to define a function especially if you are dealing with a lot of potential arguments. We could change our function definition to the following:

def letter(**kwargs):
    output = "Dear {},\n My name is {}. I want to talk to you about {}.\n{}\n Sincerely, \n{}".format(kwargs['addressee'], kwargs['author'], kwargs['subject'], kwargs['other_content'], kwargs['author'])
    return output

This makes it much easier to define the function and allows for a much more sophisticated way to write code.

Guided Exercises

We will go through a couple more exercises to understand how to use Python.

Palindrome Checker

A palindrome is a word that is the same forward as it is reversed. So, "dad" and "mom", for example are palindromes. Let’s write a function to check for a palindrome. We aren’t going to do this in the easiest way, because I want to go through a lot of the concepts we have already reviewed.

First, let’s brainstorm. We know that we will need to reverse a word at some point. Of the data types we know, list has a reverse() method.

def palindrome(word):
    reversed_word = list(word)
    reversed_word.reverse()
    reversed_word = "".join(reversed_word)
    if reversed_word == word:
        return True
    else:
        return False

So, what did we do? First, we converted the string word into a list, such that each element is a letter of word. Then, we reversed the list. Lastly, we used the join() method. This takes a string, and joins all of the elements within the argument. Lastly, we checked if reversed_word is the same as word. If so, we return True, else we return False.

Let’s try to improve this. Since we are only returning True or False, we can just return the if condition. So, an improvement would be:

def palindrome(word):
    reversed_word = list(word)
    reversed_word.reverse()
    reversed_word = "".join(reversed_word)
    return reversed_word == word

Returning the condition like this is a very easy trick to decrease any unnecessary if statements

TIP:There is an even better way of doing this. Look up more advanced ways of indexing, and you will be able to make this code even more efficient.

Pyramid of Stars

Let’s try another example. I want to create a function called pyramid. This function will take an integer and will print out a pyramid with a total number of rows that are given as an argument. For example:

pyramid(3):
  *
 ***
*****

This one is a little trickier. Let’s think this one through as well. The first row will have one star, the second row will have three starts, the third will have 5 and so on. So, the number of stars per row will be odd, and increase by two.

We also need to look at the number of spaces in each row so that it is nice and centered like the one above. The first row has two spaces on each side, the second row has one space on each side and the last row has no spaces on each side. It seems that the first row will have spaces on each side and will decrease each row.

Table 7. Pyramid
Row Output Number of Spaces Number of Stars

1

*

2

1

2

*

1

3

3

*

0

5

We have a table that shows the row by row calculations. When row = 1, the spaces = 2. When row = 2, the spaces = 1. When row = 3, the spaces = 0.

So, it looks like we can define spaces as spaces = total_rows - row. Now, let’s look at the number of stars. When row = 1, the stars = 1. When row = 2, the stars = 3. When row = 3, the stars = 5.

This one is a little trickier. You may want to do a few more rows, but it looks like the way to calculate this is stars = row * 2 - 1. So, let’s start coding this.

def pyramid(rows):
    for i in range(rows):
        spaces = rows - (i + 1)
        stars = 2 * (i + 1) - 1

Let’s walk through this for a second. We know that i in that code starts at 0. So, we need to increase the counter, i, by one in order to get the current row, if we are counting the rows starting from 1. We do the same with the number of stars.

Next, we need to create the string that holds the output for the row. There is a little trick that we need to use - the * operator for strings. If you multiply a string by an integer, then you will get the original string repeated by the number you multiplied it by. For example, in the console:

4 * "hello"
>> "hellohellohellohello"

So, try to apply this to the pyramid function.

We will add the following line:

        output_row = spaces * " " + stars * "*"

Then, you print output_row. The final code should look like this:

def pyramid(rows):
    for i in range(rows):
        spaces = rows - (i + 1)
        stars = 2 * (i + 1) - 1
        output_row = spaces * " " + stars * "*"
        print(output_row)

This is a very short algorithm, but it does help you think like a programmer a little bit more.

Object Oriented Python

Python is an object oriented language. That means that you will typically write your code relative to objects. An object (also called a Class) in Python has attributes (also called properties) and methods (functions). We will review objects from a fundamental level, and then look at three concepts of object oriented programming - encapsulation, inheritance and polymorphism.

Introduction to Objects

In order to create an object in Python, you will use the class keyword.

Let’s create an object called JaredGoff, which will describe the quarterback of the Los Angeles Rams.

class JaredGoff:
    first_name = "Jared"
    last_name = "Goff"
    position = "Quarterback"
    team = "Los Angeles Rams"
    jersey_number = 16

Naming conventions for Python objects is to have no spaces between the words and to capitalize the first letter of each word, as shown in JaredGoff. We just created the object. But, this is just the object. Now, we need to create an instance of the object. We do this by:

person = JaredGoff()

If we want to access the different attributes, we can do so by the following:

person.first_name
>> "Jared"
person.last_name
>> "Goff"
person.jersey_number
>> 16

Objects can also have methods. In order to create a method in our object, we will just define a function within our object.

class JaredGoff:
    first_name = "Jared"
    last_name = "Goff"
    position = "Quarterback"
    team = "Los Angeles Rams"
    jersey_number = 16

    def describe(self):
        return "{} {}, #{}, is a {} of the {}".format(self.first_name, self.last_name, self.jersey_number, self.position, self.team)

All custom methods in an object will need the self keyword as a first argument. This helps the method access other properties and attributes within the object. When we call the function, we will implicitly be sending the self argument as the first argument. If we use the above code, we can access the describe() method.

print(person.describe())
>> Jared Goff, #16, is a Quarterback of the Los Angeles Rams.

This is great and all, but this object only refers to one person, so having multiple instances of the JaredGoff class does not really do anything. Next, we will learn how to create an object that is more customizable.

Using init

Python has a built in method for objects, called init(). This method is called whenever a new instance is created, and allows us to create a more dynamic object. Let’s make an object called Player to show as an example.

class Player:
    def __init__(self, first_name = "", last_name = "", position = "", team = "", jersey_number = 0):
        self.first_name = first_name
        self.last_name = last_name
        self.position = position
        self.team = team
        self.jersey_number = jersey_number

    def describe(self):
        return "{} {}, #{}, is a {} of the {}".format(self.first_name, self.last_name, self.jersey_number, self.position, self.team)

Now, we can create different instances of Player objects. We would do this in the following way:

jared_goff = Player(first_name="Jared", last_name="Goff", position="Quarterback", team="Los Angeles Rams", jersey_number=16)

Now, we have an instance of the Player object, jared_goff. We still have access to the properties of Player.

jared_goff.first_name
>> "Jared"
jared_goff.last_name
>> "Goff"
jared_goff.jersey_number
>> 16

Because we have a class with an init class, we can make another instance that has similar properties and methods.

todd_gurley = Player(first_name="Todd", last_name="Gurley", position="Running Back", team="Los Angeles Rams", jersey_number=30)
print(todd_gurley.describe())
>> Todd Gurley, #30, is a Running Back of the Los Angeles Rams

Encapsulation

We have learned what an object is. Let’s dig into terminology a little bit more. The object definition is the part of code that creates the object’s properties and methods, which is the code following the class keyword.

An object instance is a specific implementation of your class. So, in the previous section, jared_goff would be an instance of the Player class.

Encapsulation refers to the ability to manage the data of a class. Although it exists in Python, it is a much smaller concept than other languages, such as C++ or Java.

Inheritance

Inheritance is a part of object oriented programming that really shows just how powerful objects are. Inheritance allows you to create a new object that inherits properties and methods from another object. So, if there are a few different objects that have similar methods, you can create one object that holds the similar methods/properties and then inherit from that object.

As always, let’s jump right into an example. All Python objects implicitly inherit from Python’s Object class. So, the following are equivalent:

class MyObject:
    # methods and properties go here
class MyObject(object):
    # methods and properties go here

The parentheses after the class name contain the name of the object that you will be inheriting from. So, let’s look at a more complicated example.

class Cat:
    def __init__(self, name="", age=0, weight=0)
        self.name = name
        self.age = age
        self.weight = weight

    def meow(self):
        print("Meow")

class Dog:
    def __init__(self, name="", age=0, weight=0)
        self.name = name
        self.age = age
        self.weight = weight

    def bark(self):
        print("Bark")

We notice that the init method has the same code in both the Cat and Dog class. They both have the name property so we can assume they are pets. Let’s make a Pet object with the same init class.

class Pet:
    def __init__(self, name="", age=0, weight=0):
        self.name = name
        self.age = age
        self.weight = weight

Now we can redefine the Cat and Dog class.

class Cat(Pet):
    def meow(self):
        print("Meow")

class Dog(Pet):
    def bark(self):
        print("Bark")

Both Cat and Dog have the init() method just as defined as in the Pet object. Then, we can add whatever methods we want to them when they are inherited from Pet.

What if we wanted to add another property to our class Dog? Could we still use inheritance, or would we need to rewrite our entire object? This is where super() comes in.

super()

When you want to use the methods and/or properties from another class that you are inheriting from, but still need to change some of the methods, you can. This is done using super(). What this essentially does is call the predefined method within the method itself.

class MyObject(MyOtherObject):
    def method(self, arg1, arg2):
        super().method(arg1)

This will send the arguments from the MyObject init method to the init method from MyOtherObject. You can only send in the arguments that apply to the object arg. Then, we can add other properties into the init method.

Let’s look at the example by adding the breed property to the Dog class.

class Dog(Pet):
    def __init__(self, name="", age=0, weight=0, breed=""):
        super().__init__(name, age, weight)
        self.breed = breed

    def bark(self):
        print("Bark")

In the console:

air_bud = Dog("Air Bud", 2, 65, "Golden Retriever")
print(air_bud.name, air_bud.breed)
>> Air Bud Golden Retriever

It will create an instance of class Dog using the init method from Pet class. Then, we can extend the usage by adding more logic and lines of code. This will be heavily utilized when we get into Django, so make sure you understand this concept. It will make more sense as you see examples in Django.

Multiple Inheritance

The great thing about inheritance is that you can inherit from multiple objects. This means that an object can inherit the objects and methods from multiple objects.

In Python, syntax for this is easy. All you would need to do is to add another object within the parentheses when creating an object.

class MyObject(MyOtherObject1, MyOtherObject2):
    #code goes here

In this example, MyObject inherits from both MyOtherObject1 and MyOtherObject2.

Polymorphism

Polymorphism is the idea that the same method can be performed on different objects. We want to be able to use the same method for different classes, such as the addition operator.

Let’s look at the example of the Dog and Cat objects. The Dog object has a bark method and the Cat object has a meow method. These are two methods that allow us to know the noise that the Dog or Cat instance make.

Let’s add the following method to the Pet object.

class Pet:
    # other methods
    def make_noise(self):
        print("Generic pet noise")

Now, when the method make_noise is called, it will make the noise of the Pet parent class. However, whenever we make a new object that inherits from the Pet class, we want to design it so that we call the same method regardless of the class.

So, when we define the Dog and Cat object, we will not define a bark and meow method, but we will know define a make_noise method.

class Dog(Pet):
    #other methods
    def make_noise(self):
        print("Bark!")

class Cat(Pet):
    #other methods
    def make_noise(self):
        print("Meow!")

Now, we have a uniform way to call a function that performs a parallel operation.

Let’s look at a more practical example - the addition operator. We can look at the simple integer data type in Python. If we want to add two integers together, we can simply use the + operator. Let’s say we want to create a new object, called ComplexNumber. ComplexNumber will have two properties - real and imaginary. A complex number is simply a number in mathematics that has both a real component and a imaginary component, using i as the variable for the imaginary component.

When we add two complex numbers, we add the real part together and the imaginary parts together. So, (3 + 4i) + (2 - 3i) = (3 + 2) + (4 - 3)i = 5 + i.

Let’s access the add method in the object.

class ComplexNumber:
    def __init__(self, real, imaginary):
        self.real = real
        self.imaginary = imaginary

    def __add__(self, other_complex_num):
        real_sum = self.real + other_complex_num.real
        imaginary_sum = self.imaginary + other_complex_num.imaginary
        return ComplexNumber(real_sum, imaginary_sum)

Now, we have overridden the + operator for this object. We can now do the following in the console.

cnum1 = ComplexNumber(3, 4)
cnum2 = ComplexNumber(2, -3)
complex_sum = cnum1 + cnum2
print("{} + {}i".format(complex_sum.real, complex_sum.imaginary))
>> 5 + 1i

We can do the same with all other operators when we want to perform operations on complex numbers.

Introduction to Django and Back End Development

We have finally reached Django! I hope you are excited. We will finally be putting together all of your knowledge and learn how to create full stack web apps. This chapter will first focus on high level definitions and concepts, and then we will jump right into Django. Try not to stress out too much when we make our "Hello World" program. I will be flying through many different concepts - I just want to get you familiar with the overall picture. The following chapters will go more in depth about the different parts of the Django environment.

Understanding the Back End

The back end of a website, in simplest terms, is the part of the website that deals with the data of the website. You can think of most websites and web apps as a database with a mask on it. Let’s consider at a simple example - what if you wanted to make a version of YouTube from scratch. Well, there are a few things to consider.

First, you want to look at the user’s point of view. What is the easiest way for them to post videos, search videos and interact with other users? Next, you want to look at the back end - what is the best way to store all of the videos and information, such as users, video descriptions, video names, etc.? You will make a database that holds all of this information. If you really wanted to, you can just make a database, then make everyone learn SQL so that they can query different videos and users. Or, you can put a mask on the database - and create buttons to perform different queries.

Let’s say you wanted to search for a video. A search bar and a search button are all you need to create a simple query in the database. This is the "mask" that makes it easier. But the main functionality of dynamic websites comes from the back end.

Note
I am not sure if I had heard of this "mask" metaphor from someone else If I am suing someone else’s metaphor, let me know and I will give proper attribute.

Django is a back end framework that uses Python. Flask is another framework that uses Python. Node.js is an extremely popular one that uses Javascript. Ruby on Rails is one that uses Ruby. There are many different frameworks, and Django is just one of them. When you hear these terms being thrown around, they are simply ways to help build out dynamic websites using different languages.

Servers and Databases

Before we start going into Django, we should talk about servers and databases on a higher level.

A server can be thought of as a computer that performs tasks. I purposely left this as a vague, general statement because it will help you actually understand what it is. When you are accessing a website, you are asking for something from a server. The server is what stores all of the information and gives you the data and/or files back.

So, when you go to www.google.com, you are asking Google’s server to display the .html file that will help you search for whatever it is you are looking for. Your computer can act as a server. In fact, when you are developing an application locally, you will use your computer as the server. Django has a very easy way to do this, and you will be able to get up and running quickly.

When you deploy your app, you will essentially be copying all of your project files to another location instead of your own computer. We call your local environment your development server and the server you will be using for deployment your production server.

A database is a collection of data. Databases can be in various different formats. An easy example is in Excel. If you want to create a database, you can create a new workbook. Each sheet will be a table. You can save this workbook with all of the information, and it will be, in effect, a database.

However, when we are talking about back end development, we are not referring to an Excel spreadsheet as a database. Databases will typically rely on a language called Structured Query Language (SQL). SQL is a widely used language that helps manage the data in your databases through queries. A query is a command that will create, update, retrieve or delete data in your database.

When you are making a Django project, your data will likely be held in a database that uses SQL. Django makes it easy to communicate with SQL databases, as we will learn.

What is Django

Django is a web development framework that is written in Python. It creates an easy way to create large, scalable web apps that can easily link up the front and back end. Django is a combination of many different modules that allows for things such as serving static files on the front end, managing your database schema, and organizing your routing.

Django’s official website brands Django as "The Web framework for perfectionists with deadlines." You can get it up and running extremely quickly, and it is very programmer friendly. Let’s see how it works from a high level point of view.

Model View Template (MVT)

Django is built on the Model-View-Template (MVT) framework. The MVT framework is how a web app is organized when going between the front end (client side) and back end (server side).

Model View Template
Figure 36. Model View Template

As you can tell in the figure above, there are a few steps to see how Django works under the scenes. First, you start off at your computer. Let’s say you go to a website that is built with Django. It goes to the website address, let’s say www.codexplore.io. When it visits this website, it looks through all of the possible URL routes to look for the route that you submitted. Once it finds the URL route, it will call for a View to be shown to the user.

The View can show static data or can access the database. If it is static, the view just returns a Template (html) file to the url router and displays it on the screen for the user. If the View needs to access the database, it will do so by looking through the Models and returning a query to the View. Once the View has the data, it will send the data to a Template to display the data on the .html file, and then send that template back to the url router which will send it to the user.

It can be easy to think about it as an assembly line. Every stop is going to be a function that is called, and will likely return another function or some other information. It will go down the assembly line by calling all of the functions. Then, when it reaches the final function call, it starts returning all of the information back to the functions and will eventually return the .html file to the client. Let’s start using Django to see how Django projects are organized within the actual code.

Installing Django

Since you have Python already installed on your computer, you can easily install Django using the following command

pip install django

This command will install the most up to date version of Django. The most current long term support (LTS) version of Django is 1.11, but it is not the most current version. This book uses any version of Django 1.11 and later, so you can use whichever version you would like. I will make sure to explain any major differences in implementation between different versions as we go along.

First Django Project

Now that we have Django installed, open up a command prompt. Once the prompt is open, navigate to a folder, or create one in the prompt. It can be saved in any part of your computer that you want. A Django project is just a collection of python files, so you can save those files in a place that is most organized for you.

Once you are in the directory that you want to create your Django project, type the following command:

django-admin startproject myproject

There are three parts to this command. First, we type in django-admin. This let’s our computer know that we want to create a Django app, and that the following code will correspond with Django’s commands. The next part is startproject. This tells Django that we want to create a new Django project, and it will create all the files and folders that we need to do so. Lastly, we typed in myproject. Django will name the project "myproject". We could make this last argument anything we want, as long as it follows Django’s naming guidelines. It will reject any names that are incompatible with Django.

Let it take some time to create the project if it does take time. Once you do, open the project in your favorite text editor. I use Atom, so a blank project will look like the following:

First Django Project
Figure 37. First Django Project

In Atom and most text editors, the folder you are in will show up on the left side and you can expand or shrink what you see.

Django projects have a subfolder that is the same name as the project. This subfolder has the default project level folders.

Django environment walkthrough

First, the init.py file is simply a Python convention for things like importing. Next, there is the settings.py file. This is an extremely important file that we will be using quite often. When you open it, you will see many different variables. These are all variables that your project will be using when calling different functions and performing different tasks. You will notice as you scroll through this file, that it is simply a collection of strings, lists, dictionaries and other variables. We will not go into specifics of each variable now, as it will only make sense while we progress through Django.

After our settings.py, we see our urls.py. This file is where all of our urls will be saved. We will have different patterns that the user can browse. Django will look for the url pattern that is in the address bar. We will go into this later.

The last file is not a large concern for a while. wsgi.py is a configuration file when your project is deployed. We will get into this later, but it is good to know that it is there and what it generally does.

A Django project is built with many different apps. This seems a little confusing, because we have been talking about building a web app. Within the Django framework, the Django project will be your web app. The Django project is then broken up into different apps that do different specific functions for your project.

In the command prompt, make sure that you are in the Django project folder. If you list the files in the directory, you will see the myproject folder and a manage.py file.

Let’s say we are making a blog project. We will make an app that specifically deals with blog posts. In terms of architecture, each app will be named after the main data table (or Model) that your app focuses on. So, we will create a data table to hold all of the posts. We will go more into specifics when we learn about Models.

In order to create an app, we type in the following line of code

python manage.py startapp posts

There are four parts to this command, so let’s walk through them. First, python tells the command prompt that the following code will be a Python command. manage.py runs the python script manage.py that is located in your project directory. Then, startapp will tell the manage.py script which command it will run. If you are bored, you can look into the manage.py file and then look at the Django docs to understand those two steps more. The last portion defines the name of the app, posts. This can be named anything you want within the guidelines of the Django naming conventions.

When you run this command, wait for it to complete. Your Django project will now look like this in your text editor.

Django Project with Posts App
Figure 38. Django Project with Posts App

A new folder has appeared! Congratulations on making your first app. We have also been introduced to a few new Python files.

First, we have admin.py. This file will deal with features on the admin section of your website relative to this app. Each Django project has an already built out Admin interface that allows you to work with your project easily.

Next, we have apps.py. This is really outside the scope of this book.

Then, there is models.py. This will be where you will put your Model - the "M" in MVT - for your app. We will eventually create an object in here called Post, which inherits from models.Model, but we will get there.

tests.py is where you will put code for testing your other code. We will not be using this much in the context of this book, but writing tests for your code can save you a lot of time.

Lastly, but certainly not least, we have views.py. This is where we put all of our views for our app, the "V" in MVT.

Whenever you create a new app, you need to go into your settings.py for your project, and scroll down to the INSTALLED_APPS list. Then, you write the name of your new app in the list. It should look like the following:

Adding new app to `settings.py`
Figure 39. Adding new app to settings.py

We will learn why this is important in more detail, but make this a habit whenever you create a new app.

Hello World program

Let’s start with our first app. Go back to the command prompt and type the following command in:

python manage.py runserver

This is a very powerful command that is worth looking at. Django works by using Python. Python is a language that requires some sort of execution, so Django will need to run on a server. What this command does is create a local server that will serve as your development environment. Once you run this command, you will see the following in your command prompt:

Starting up Django server
Figure 40. Starting up Django server

There is a line that starts with "Starting development server at…​" after running the runserver command. If you copy the url in that line into your address bar, you will see something like this:

localhost:8000
Figure 41. localhost:8000

This is your main page. When you go to your url, in this case, localhost:8000, it will display this page, unless you decide otherwise. We will walk through how to make a page that displays "Hello World!".

First, we need to start adding templates. In your project folder, create a new folder called "templates". This is where you will keep you .html files. There are a few different design patterns for templates that we will learn, but this is where we will start.

Next, go to your settings.py. Towards the top of your settings.py, there is a variable called BASE_DIR. This is a definition for your project that tells you the path of the project directory, and will format it. Underneath the definition of BASE_DIR, add the following,

TEMPLATE_DIR = os.path.join(BASE_DIR, 'templates')

This creates a new variable that stores the location of your template - that is, the folder that you just created. Then, scroll down further in your settings.py and look for a variable called TEMPLATES, which contains different settings and options for your templates for your Django project. Within this list is a dictionary. There is a key called DIRS, with a value of a list. The value of this item will be a list of locations of where your templates are saved for your Django app. Within this list, type in TEMPLATE_DIR - the variable you just defined. So, this will look like the following:

settings.py
Figure 42. settings.py

We have now set up our Django project to know where to look for our templates. Our goal is to create a template that says "Hello World" when we visit "localhost:8000". In the MVT framework, we do not have a model, as there is no data that we will be accessing - just static information in the form of "Hello World." We need to create a view so the browser can ask for a template. We have also created a 'templates' folder, but we still need an .html file as a template.

In your 'templates' folder, create a new file called "hello_world.html". In this file, type the following code:

<h1>Hello World!</h1>

Our Django project needs to now be told how to show this .html file

Go to your posts folder and open the views.py file. Within this file, we will be writing functions and classes that will handle our views in the MVT framework.

Type the following after the imports.

def hello_world_view(request):
    return render(request, 'hello_world.html')

This function takes in the request, and will eventually resolve by returning an .html file (in conjunction with the urls.py file). Your views.py file should look like the following:

views.py
Figure 43. views.py

Last, we need to create code in our urls.py file that will tell our Django project which route will handle our hello_world.html file In the "my_project" folder, open the urls.py file. You will have a list of URL patterns in the form of a list called urlpatterns. This tells the Django project which routes to look for. Django’s URL patterns will need a function to execute so that it knows how to display the template. We will be giving them the hello_world_view function. So, first import the function after the project imports:

from posts.views import hello_world_view

Next, add the following line to the urlpatterns list.

path('', hello_world_view)

Your urls.py file should look like this:

urls.py
Figure 44. urls.py

Now, we should be ready to go. If you no longer have your Django server running, type python manage.py runserver into the command prompt. Otherwise, just refresh the browser you have open. It should look like the following:

Hello World
Figure 45. Hello World

Congratulations! You have just made your first Hello World Django project. Obviously this is a lot of work for just a static website. This situation would be much easier by just making an html file. However, a we will see, Django’s strengths come from displaying dynamic content.

Django Framework Part Two

In the previous chapter, we learned how to quickly create a Django project. However, we skipped over a lot of explanations. This chapter will focus on how Django works in more detail. We will begin creating your first Django project, which is a blog.

Views

In the previous chapter, we created functions in posts.views.py. You can generally think of a view as a one-to-one relationship with each url route. When you go to somewebsite.com/route, this should correspond to one view.

So, we will begin creating views that will be used to perform CRUD functionality for our posts. First, let’s go back into our posts.views.py and delete the hello_world_view. Let’s start with the create part of CRUD for our blog posts.

def post_create_view(request):
    pass
Note
It may be a little confusing at this point: our app is called posts, but we will also be dealing with POST requests. This are not the same at all, and the posts app is used to create blog posts.

Where do we even start? Well, when you a user is creating a blog post, they are submitting a request. If they are sending information via a form to create something in the database, we will be relying on a POST request. If they have just visited the page and are about to create something, it will be via a GET request. The request argument that is passed to our view holds this information.

def post_create_view(request):
    if request.method == "POST":
        # create a blog post
    else:
        #showt he blog post form

We have not created a model for posts in our posts.models.py yet, but we can still get part of this completed. If the request is not a POST request, the request is just asking to see the form. So, we will just return a template that holds a form.

def post_create_view(request):
    if request.method == "POST":
        # create a post
        pass
    else:
        return render(request, 'posts/create.html', context)

As you can see, we will be rendering the template located within the posts folder called create.html. Let’s go over and create one. We can delete the hello_world.html file and create a new file within a new subfolder. Our project folders should now look like this:

New template
Figure 46. New template

Within the templates folder, we have a posts folder with a new .html file. This is what will be displayed when the user submits a GET request. Our create.html will have the following:

<form method="POST">
    <input type="text" name="post-title"/>
    <input type="text" name="post-content"/>
    <input type="submit" value="Create" />
</form>

We can now see how the user will submit a POST or a GET request. If they just visit the page, the form will display. If they submit the form, it will put in a POST request, and our first if statement within post_create_view will be True.

Now that we have that, let’s create a route in our urls.py. In the previous chapter, we imported our views within the main urls.py file. However, as you have larger and larger projects, you will realize that it is hard to list all of the urls in that one file. So, there is a fancy method called include that will help us out with that.

First, create a new file within your posts app called urls.py. This will contain all of the urls for this specific app. Within posts.urls.py, we will need to import path. We will also need to define a variable called app_name. This is for Django so that it can find the urls.py file for this app. Then, just as our main urls.py file has them, we will need to create a list of urlpatterns. Your project should now look like this:

Posts urls.py
Figure 47. Posts urls.py

Now, we need to go to our main urls.py and delete our now irrelevant hello_world_view import and the path associated with it. We will also want to import include so that we can include all of the urls from our posts.urls.py file. Your my_project.urls.py file should now look like this:

my_project urls.py
Figure 48. my_project urls.py

Instead of putting the view in the second argument of the path function, you put the include function. This will, you guessed it, include all of the url patterns from the file you are referencing. Then, we make a namespace argument. This will help use call the view in our templates.

Let’s make sure to start the server using python manage.py runserver. Then, go to your browser and visit "localhost:8000/posts/create". You should see the following:

post_create_view
Figure 49. post_create_view

Now, let’s do something similar for the next CRUD views: Retrieve/detail. In this view, we will not need to worry about a POST request, because there is no form that will be submitted. We will then write a simple function.

def post_detail_view(request):
    return render(request, 'posts/detail.html', context={})

Since we do not have our database set up yet, this is all we can do to set up the view. Now, we need to make a template again. Simply add a new .html file called detail.html within your "templates/posts" folder. Then, we need to add the url pattern to our posts.urls.py.

posts.urls.py
Figure 50. Updated posts.urls.py

Note that we changed the arguments in the path function and also imported the new view. Let’s now make a list view that will simply give a list of all the posts. This will never have a POST request either, so we can do the same thing as post_detail_view.

def post_list_view(request):
    return render(request, 'posts/list.html', context={})

We once again need to create our template and update the posts.urls.py. Now, we need to add two more views - the update and delete views.

These will be similar to the post_create_view because they will be changing the database. First, the post_update_view.

def post_update_view(request):
    if request.method == "POST":
        # update the post
        pass
    else:
        return render(request, 'posts/update.html', context)

We will also need to create a template that contains a form as well. Then, we update our urls.py and change the arguments in the path function.

We will need to create our post_delete_view. This one is a little trickier. Let’s think about what we want out of our delete view. We will likely press a "Delete" button for our post, and then we will be prompted with a message "Are you sure you want to delete this post?". So, once we click the delete button, there will be a GET request to it.

def post_delete_view(request):
    if request.method == "POST":
        # delete the post
        pass
    else:
        return render(request, 'posts/delete.html', context)

We cannot do anything on the POST method yet, since we do not yet have the code set up for the database. However, we can set up our 'posts/delete.html' template.

Are you sure you want to delete?
<form method = "POST">
    <input type="submit" value="Yes"/>
    <button>No</button>
</form>

If we submit this form, we are submitting a POST request, which we will handle in the view. Then, we just add this to the urlpatterns in posts.urls.py. It now looks like:

posts.urls.py
Figure 51. Updated posts.urls.py

We have now added our basic views to the model.

Models

Now that we have been adding views to our project, we will be adding the database layer for our posts. We have all the views set up, but how would post_detail_view work if we have no posts to show? We need a database set up, so let’s first go to posts.models.py.

Notice that the first import is from django.db import models. This is Django’s main framework to help interact with the database. The "models" API helps Django programmers easily interact with the database without using SQL.

Think if each model as a table in the database. Each table will have fields and instances. If you are using an Excel worksheet, you can think of the fields as the columns and the rows as instances. When defining a model in Django, you will create an object that represents that model. Then, you will define the fields within that object.

We need to create a "Post" model (a table to hold all the data for our Posts). We will need the Post Title and the Post Content. Let’s also create timestamps so that we know when it was created and when it was last updated. The syntax is as follows:

class Post(models.Model):
    post_title = models.CharField(max_length = 150)
    post_content = models.CharField(max_length = 5000)
    created_at = models.DateTimeField(auto_now_add = True)
    last_updated = models.DateTimeField(auto_now = True)

This is a lot of information to be introduced to, so let’s go through it. First, we declare class Post, which inherits from models.Model. This tells Django that this is a new model that will have a table in the database. Then, we create properties within the object. These are called fields within the Django models API. The models framework has plenty of different types of fields. This tells the database what kind of information you want to hold in that field (or column if that makes more sense).

Our post_title and post_content are CharField s because it is holding characters. There is a mandatory argument of max_length in this particular field so that Django knows how many characters it should leave room for. In order to access the fields, you need to use the dot operator from the models import.

Next, we have our timestamp fields. They are both models.DateTimeField s, but have two different arguments. The auto_now_add argument means that the database will automatically save the date and time when a new instance is added to the database. This is exactly what we want for the created_at. However, for last_updated, we want it to update with the current time at every save. The auto_now argument, when set to True, does just that. You don’t need to worry about memorizing the fields, as Django’s website has in depth documentation

Now that we have our model coded, we need to actually send it to the database. Django does not automatically create the database whenever models are changed - you need to explicitly tell it to. So, there are two commands you need to remember - and trust me, you will.

You will open your command prompt in your project and type

python manage.py makemigrations

Migrations will create a current picture of your models and database. However, it will not apply those changes to your database. It helps deal with any errors and can help you keep track of the changes you make. In order to apply the migration to your database, type the following:

python manage.py migrate

This will now apply the changes to the database. If you have done everything right, you have just created your first database! We can check it in the console. Django has a way to interact with your Django project within the command prompt.

python manage.py shell

You should see something like this in your command prompt now:

Django Shell
Figure 52. Django Shell

Now, we can use the Django API to check with the database. We will be covering querysets in the next section. A queryset is a data type that holds information from your database. The syntax, in general, is as follows:

ModelName.objects.method()

The term objects accesses the model’s manager and helps you access and manage instances of that particular model. Then, you put in any method you want within the API. For example, all() will return all instances of the model in the database.

So, let’s go back into our command prompt and mess with our Post model.

All Post Instances
Figure 53. All Post Instances

We did a query for posts by typing posts = Post.objects.all(). Then we created a list so that we can see the title of the post by accessing the post_title property of each post. However, this returned an empty list because we have not created any instances. So, let’s do that with the following command:

new_post = Post.objects.create(post_title = "My First Post", post_content = "My first post content")

This will create an instance and save it to the database. So, we can redefine our queryset to grab all of the instances, and when we print out the post_title, we have a non empty list.

Create Post
Figure 54. Create Post

You may have noticed that we have created a redundancy. When we create a post, the post will have a title. However, we called the field post_title. We can just call it title. This can be the same with post_content. Let’s change our model code to the following:

class Post(models.Model):
    title = models.CharField(max_length = 150)
    content = models.CharField(max_length = 5000)
    created_at = models.DateTimeField(auto_now_add = True)
    last_updated = models.DateTimeField(auto_now = True)

We just made a change to the model, so we will have to make a migration and then migrate that change to the database. First, you can exit the Django shell by typing the exit() command. So, as always, we will type python manage.py makemigrations. Sometimes you will make a change, but it will say "No changes detected". If this is the case, you can put an optional argument for the specific app you want to make the migrations for. So, you would type: python manage.py makemigrations posts. One of those should work. If you have any problems with migrations, remember: Google is your friend.

We will see the following:

New Migration
Figure 55. New Migration

We have now made a new migration. We were prompted with questions about altering the field, and then it confirmed that we did. Next, let’s python manage.py migrate.

Migrating the Database
Figure 56. Migrating the Database

When you migrate the database, you will see it apply the specific migration, which it does, as you can see in the previous picture. Now that we have a handle on setting up the back end/database side, let’s incorporate them with our views.

Querysets, Views and Models

We have set everything up for the final part of this chapter: making views that actually do what we want them to do. First, we will have to understand how to use querysets, and common types of them. Then, we will incorporate them in our views, so that we can create instances of the model within our .html templates on the client side. Hopefully after this section, you will have a much better understanding of how the front end works with the back end.

Querysets

A queryset is a data type that is part of Django’s API. As said before, a queryset helps us interact with the database. We typically access it using the .objects property on the Model itself. We will go through the most common query methods, while also keeping in mind that there are many others that you can use.

all()

We saw this in the previous section. If we type posts = Post.objects.all(), posts is now a queryset that holds all of the instances of the Post model. It is as simple as that. We can then iterate through them.

create()

We also saw this method in the previous section. The create() method accepts arguments of the fields that we used in the model. So, if we wanted to write a post about the Rams, we could do the following:

post = Post.objects.create(title="The Rams are the best", content = "Todd Gurley should be MVP")

This will now hit the database with a new instance.

get()

If we are looking for a specific instance of the Model, we can use the get() method. Something to know is that all models automatically are given an id field. So, we can get a particular instance based off of the id:

post = Post.objects.get(id = 1)

The problem with get() is that it will create an error if none exists. That is where filter() comes into play.

filter()

This is one of the most widely used methods because it helps you retrieve more specific instances of your model. It will take arguments of your field names as arguments.

posts = Post.objects.filter(title = "The Rams are the best")

This will return a queryset such that all titles are "The Rams are the best". If we had multiple querysets of the same title, we have all of those within the same queryset. But, if there are not posts that have that title, we will return an empty queryset without an error, which can make it a better option than get(). Remember: filter() is iterable.

get_or_create()

Another option instead of get() is get_or_create() which will look for a specific instance, and if it does not exist it will create it.

post = Post.objects.get_or_create(pk = 4, title = "Get or Create", content = "New Content")

This command will return an object in the database that fits all of the arguments exactly. Otherwise, it will create an instance with the arguments given.

delete()

Up to this point, we have only been looking at methods from the objects property. However, we would like to also look at methods we can perform on specific querysets. The delete() method is performed on a queryset and will delete all the instances within that queryset.

post = Post.objects.filter(pk=1).delete()

This will delete all those posts within that queryset from the database.

update()

Let’s now say we want to update/change a post. We simply grab the post that we want through whatever way we want, and then use the update() method afterwards. The update method will take in field arguments and then change the instance accordingly. Let’s say we have a post with a title "The Rams are the best" and we want to change it to "The Rams are the absolute best". We would do the following:

post = Post.objects.filter(title = "The Rams are the best").update(title = "The Rams are the absolute best")

Note that you can apply an update to more than one instance at a time.

first() and last()

This is very handy when dealing with filter(). If you are dealing with a queryset that is iterable, you will sometimes want to get the first instance. This is the case if you are using filter() to return all instances that have id = 1. We know that at most there will be one instance returned. However, if we use the first() method on the queryset, it will return the first instance in that set. This works like the following:

post = Post.objects.filter(pk=1).first()

Front End and Back End Interacting

Now that we know how to use Python to interact with the database, let’s update our views so that our views actually do the thing we want. We will be going through each of our views so that we can see how to interact with the database. However, we will be going in order of easiest to most difficult, instead of the same order we previously used. We will first start off with the easiest case - post_list_view.

Post List View

We will need to use Python to get all of the data and then send the data to the template. This is done via the context argument in the render() function. The post_list_view will show a list of all of the posts in the database. We will import the model into our posts.views.py first. Then, we can perform the all() method.

def post_list_view(request):
    posts = Post.objects.all()
    context = { 'posts': posts }
    return render(request, 'posts/list.html', context=context)

We create a posts variable to hold the queryset. Then, since context is a dict, we will create a key of 'posts' and assign the posts variable as the value.

Let’s now go over to our template. We will learn a new "language" to use the context in the templates - the Django template language. You use this language to display the Python context in the html document. The syntax for the Django template language involves wrapping logic within the braces and percentage signs {% logic goes here %}. For anything you want to display in the template, use double braces: {{ content goes here }}. For example:

{% for p in posts %}
    {{p.title}}
{% endfor %}

If we have a key in our context dict called 'posts', we access it within this Django template language. Our logic falls within the {% %} and the output falls in the {{}}.

Now that we have reviewed this template language, we can add it into our posts/list.html template. We will want to do some brief styling. Let’s say we want the post title to be within a <h3> tag and the content to be within a <p> tag. And then we want an <hr /> between the posts. We will change our posts/list.html file to the following:

{% for p in posts %}
    <h3>{{p.title}}</h3>
    <p>{{p.content}}</p>
    <hr />
{% endfor %}

If everything was done correctly, when we go to the 'localhost:8000/posts/list' we will see the following:

Post List View
Figure 57. Post List View

The only post we have in our database is the one we made in the Django shell earlier. But, it is working. We are looping through all of the posts we provided in the context.

Post Detail View

When we need to find a specific instance in the database, we need to provide the view with a way to look it up. That way, we have a way to get a queryset based on a filter. The way we do this is by passing it via the url. In your posts.urls.py, change the detail_view path to the following:

path('detail/<int:id>', post_detail_view, name='detail')

What does the <int:id> mean? This is a Django specific way to send an argument through the url. The first part, int tells Django the type of the argument being sent in. Then, the id part tells us the name of the argument that we will be able to access in the view. What we want to be able to do is go to a url such as localhost:8000/posts/detail/1 and have it return the post whose id is 1 in the context to the template. Since we are sending another argument to the view, we should update our function declaration for post_detail_view. Then, we will have to send the post whose id is sent in the url to the template via the context. Our post_detail_view should look like the following:

def post_detail_view(request, id):
    post = Post.objects.filter(id=id).first()
    context = { 'post': post }
    return render(request, 'posts/detail.html', context=context)

We will be sending a post via the context that is not iterable. So, the way we use this in the posts/detail.html template is the following:

<h3>{{post.title}}</h3>
<p>{{post.content}}</p>
<p>Created: {{post.created_at}} | Updated: {{post.last_updated}}</p>

This is all we need to do for the detail template. If we did it right, if we visit localhost:8000/posts/detail/1, we should see the following:

Post Detail View
Figure 58. Post Detail View

We have two views out of the way now. Next, let’s write the post_create_view. We already handled what to do if the request is not a POST request. If it is, we need to access the information in the forms in the template and save that information in a model instance. We will take care of this within the first if statement in our view.

if request.method == "POST":
    title = request.POST['post-title']
    content = request.POST['post-content']

This is the way we get the information from the template. It is sent in the request. Then, there is a POST property of the request, where all of the POST data is sent. We use the key of 'post-title' and 'post-content' because those were the name attribute in the posts/create.html file.

Next, we will need to check that the these two inputs are not empty. If they are not empty, we can create an instance and then we will redirect the users to the detail view of that post. Otherwise, we will prompt them with an error that says they need to fill out both forms.

if title and content:
    post = Post.objects.create(title=title, content=content)
    return redirect('posts:detail', id=post.id)
else:
    context['error'] = "Both Title and Content are necessary!"
    return render(request, 'posts/create.html', context = context)

there are a few things that we need to cover here. First, we check if the title and content are empty. If they are not, we will redirect the user to the detail view of post. This is imported using from django.shortcuts import redirect. This is the same location the render function is imported from.

The redirect function accepts an argument of 'posts:detail' and 'id=post.id'. What does 'posts:detail' mean? Well, this is where defining the namespace in the include() function comes in handy. The first part is the string you put in for the namespace in the project urls.py Then, there is a colon and the word 'detail'. The word 'detail' corresponds to the name we defined in the posts.urls.py for the post_detail_view path. The argument 'id=post.id' is the argument we send to the path in the url, that is, the <int:id> portion.

If title and content are not given, then we will send an error via the context, that we will want to display on the template. So, our template will now look like this:

{{error}}
<form method="POST">
    {% csrf_token %}
    <label for="post-title">Title</label>
    <input type="text" name="post-title"/>
    <br />
    <label for="post-content">Content</label>
    <input type="text" name="post-content"/>
    <input type="submit" value="Create" />
</form>

The {% csrf_token %} is a Django specific tool that adds a layer of security to the form submission. We will not get into the specifics of this part in this book, but it is important to know. Django will not let you submit a form without this CSRF token. We also added some labels and line breaks to make it look a little better.

So, let’s give it a try. Let’s first clear the database via the Django shell and using the Post.objects.all().delete() method so you have a clean database in case you were playing with the database. Now, let’s go to localhost:8000/posts/create. We have two inputs. If we submit it with only the 'post-title' filled out, we get the following:

Post Create Error
Figure 59. Post Create Error

The error pops up. But, if we type in valid inputs and create, we will get redirected to the detail view.

Post Create Error
Figure 60. Post Create Error

Now that we have typed the post_create_view and it is working, let’s move onto the final two views: post_update_view and 'post_delete_view'.

Post Update View

The update view is going to mix the techniques we used for post_detail_view and post_create_view. The post_update_view will need to access the database by returning the post you want to update/modify. Then, you will need a form to modify it.

Think about when you are on a website and you have data that has been created and you want to edit it. Typically, you will click an edit/update button, and the form will appear with the current content inside the input boxes. So, we will need to query the database to get the post, and then populate the input fields with the current data. We will then check if there is a POST request. If there is, then we will update the current instance.

def post_update_view(request, id):
    post = Post.objects.filter(id=id).first()
    context = { 'post': post }
    if request.method == "POST":
        # update the post
        pass
    else:
        return render(request, 'posts/update.html', context = context)

We first needed to create the post variable by querying the database and looking for the post instance that matches the id, as we did in post_detail_view. This instance is sent in the context if there is not a POST request, so we will need to put that in the template. We do that as follows:

{{error}}
<form method="POST">
    {% csrf_token %}
    <label for="post-title">Title</label>
    <input type="text" name="post-title" value="{{post.title}}"/>
    <br />
    <label for="post-content">Content</label>
    <input type="text" name="post-content" value="{{post.content}}"/>
    <input type="submit" value="Save" />
</form>

We have a similar set up as the posts/create.html template. However, we set the value attribute in the text inputs. This will put the post.title and the post.content in the input by default. Then, the user can make changes to what is already there.

Now, we need to see what happens if the request is a POST. We will get the post-title and post-content from the name attributes like we did in the post_create_view. Then, we will check if the fields have content. If they are, then it will update, if not it will give an error. Our final function will look like this:

def post_update_view(request, id):
    post = Post.objects.filter(id=id).first()
    context = { 'post': post }
    if request.method == "POST":
        updated_title = request.POST['post-title']
        updated_content = request.POST['post-content']
        if updated_title and updated_content:
            updated_post = Post.objects.filter(id=id).update(title = updated_title, content = updated_content)
            return redirect('posts:detail', id=post.id)
        else:
            context['error'] = "Both Title and Content are necessary!"
            return render(request, 'posts/update.html', context = context)
    else:
        return render(request, 'posts/update.html', context = context)

If all is good, we will redirect to the post_detail_view via redirect.

Post Delete View

The final part of CRUD is the delete view. We have learned everything we need to know in order to create the post_delete_view, so let’s give it a shot.

First, we will need to change the url patterns so that the delete path has an argument for the id.

path('delete/<int:id>', post_delete_view, name='delete')

We have already created our posts/delete.html template. So, let’s focus on our view. If we submit the form - that is, we click the "Yes" button when asked if we are sure we want to delete, we will redirect to the list view (as the detail view will not return anything). So, if the request method is POST, then we will delete the post. The post_delete_view will have the following:

def post_delete_view(request, id):
    post = Post.objects.filter(id=id).first()
    context = { 'post': post }
    if request.method == "POST":
        post = Post.objects.filter(id=id).delete()
        return redirect('posts:list')
    else:
        return render(request, 'posts/delete.html', context = context)

We once again added the id argument, then checks the type of request, and deletes it if request.method == POST. So, to test, go to localhost:8000/posts/create and create a new post instance. You will be redirected to the detail view. You can then, replace the word 'detail' with delete in the url. If everything was done correctly, you will see the following:

Post Delete View
Figure 61. Post Delete View

If you have done everything correctly, when you press "Yes", you will be redirected to the post_list_view and the post you just deleted will no longer be there.

Congratulations! We have gotten through all of our views. The next step will make our website much easier to navigate - we will be adding links to other views within the website.

We want to be able to let the user go to views in the templates without having to go directly into the URL. We can use an <a> tag to do this, but how do we do this in Django? Generally speaking, we want to avoid using absolute url references to a specific url within our project. Django has a way to reference other views easily within the <a> tags.

The syntax is as follows:

{% url 'viewname' arg=id %}

This is what we will put in the href attribute in our <a> tags. So, let’s start on the post_list_view. It would be nice if we were able to click the title of the post, and it takes us to the post_detail_view for that instance. So, we will be changing the posts/list.html template to the following:

{% for p in posts %}
    <h3><a href="{% url 'posts:detail' id=p.id %}">{{p.title}}</a></h3>
    <p>{{p.content}}</p>
    <hr />
{% endfor %}

The argument 'posts:detail' is the same syntax that we used in the redirect function. We will then be sending the id of the current post’s id so that it can resolve to the specific template. If you have done it right, you will see your post_list_view look like something similar on the left and when you click on the title, it will take you to the right.

Links
Figure 62. Links

Now, we will think of two other ways to incorporate links so that it is easier for users. We want a button in our list view to create a new post, and then we want two buttons to edit/update and delete the post in our post_detail_view.

Let’s create the link to the post_create_view. All we need to do is put the following code somewhere on our page outside of the for loop of the posts/detail.html template:

<a href={"% url 'posts:create' %"}>Create Post</a>

The list view will now look like this:

Create Post Link
Figure 63. Create Post Link

We have a link that will take us to the post_create_view now.

Now, let’s add the other buttons to the post_detail_view. We will add the following to the end of our posts/detail.html template:

<br />
<a href="{% url 'posts:update' id=post.id %}">Edit</a>
<a href="{% url 'posts:delete' id=post.id %}">Delete</a>
<a href="{% url 'posts:list' %}">Back</a>

Now, our post detail view will look like the following:

Post Detail View
Figure 64. Post Detail View

Now, we can easily go between different views on the client side. We also added a "Back" button so that we can easily go to the list of posts again.

This chapter was a long chapter that focused on a lot of pure Django concepts. In the next chapter, we will be adding some styling to our project so we know how it works with Django. But, the emphasis will be to make our project look better.

Django Framework Part Three

We have covered how you can use Django to interact with the front end of your website. You can use views to pass information between .html files and your Django back end and other scripts.

However, how do we style our templates? We have many different .html files, so how can we use the same CSS classes across all of them? What if we want to link to let’s say, Bootstrap. Do we need to include the <link> in every .html file? That seems excessive. Luckily, Django makes it easy to organize your templates without having to repeat yourself.

Template Inheritance

Django has a very handy syntax and method to efficiently create dynamic templates. You will generally want one template to keep all of your project level stylesheets and scripts. Things like Bootstrap and JQuery would likely be included in this. We will create a project level .html file that will be inherited from in other templates.

So, let’s create that file, called "base.html" in your templates folder. It will be in the root directory of the templates folder. Just set up the .html file as if it was a normal .html file. Now, we will create the method of being able to inherit this template. Within the <body> tag, we will need to use Django template language. First, you will use the keyword block within the Django template tags. This is where your children templates will be located. Then, you use the keyword endblock to end the block.

It should look like this:

Template Extending
Figure 65. Template Extending

This is all we need to be able to extend this template so that we can inherit all of the scripts and styles from this template. The phrase base_content can be changed to whatever you want, as long as it is consistent with the name in endblock. In fact, you don’t need to even put a name in endblock. If you don’t, it will just end the block corresponding to the closest block tag. I find it helpful to repeat the name in each endblock, as it makes it easier to keep track of the content when you are nesting different templates.

This can all be very confusing, so let’s start looking at how to inherit the "base.html" content in our other templates. Let’s change our other templates so that it inherits from "base.html". First, we will need to "extend" our "base.html" template. Then, we will need to specify in the new file where the base_content begins and ends. Let’s start with our "posts/list.html".

We can change our current html to the following:

Template Inheritance
Figure 66. Template Inheritance

The first line {% extends 'posts/base.html' %} tells the template where we will be inheriting from. Then, we type the lines {% content base_content %} and {% endblock base_content %}. The way Django works is by "injecting" the content within the content tags in the child page into the base.html page.

Post List View
Figure 67. Post List View

We can tell that this works by looking at the tab. It says "Blog Project", which means the <title> tag from the 'base.html' is included with the post_list_view template. So, now that we have this, we can do the same thing with our other templates, that is 'posts/create.html', 'posts/detail.html', 'posts/delete.html' and 'posts/update.html'.

Next, we can add some style sheets and Javascript scripts. Let’s add Bootstrap to the 'base.html' file.

Adding Bootstrap
Figure 68. Adding Bootstrap

We add the stylesheet in the <head> and we will put the scripts after the content. If we refresh our post_list_view, it will look like this:

Adding Bootstrap
Figure 69. Adding Bootstrap

Now, it is updated with Bootstrap’s styles and font family. If it does not have a different style, then something has gone wrong.

Restyling the Project using Bootstrap

Now that we have Bootstrap integrated, let’s go into our templates and make them look better, starting with the 'posts/list.html'. I will be briefly explaining how to style the page, but most of the items are built on what we learned from the Bootstrap chapter. First, let’s wrap our entire base_content within a Bootstrap container. In your 'base.html', it will look like this:

<div class = "container">
    {% block base_content %}
    {% endblock base_content %}
</div>

This will give us some room on each side so the content is not hugging the sides of the viewport. Now, go to 'localhost:8000/posts/list'. It does not look good. Ideally, we would like to have a header on the page that says "All Posts", with a button to create a post. Then, we will have a list of all of the posts in the program. We can wrap the "All Posts" within an <h1> tag and use Bootstrap’s btn class for the create a post button. Then, we will add some margin to the top of the page so it does not hug against the top of the browser. Using Bootstrap, our 'posts/list.html' file will look like the following:

Post List HTML
Figure 70. Post List HTML

When we go the actual URL for the 'post_list_view', we see the following (I created more posts for filler):

Post List in Browser
Figure 71. Post List in Browser

It looks better already. Now let’s go to the create view. We will style the title of "Create New Post" in the same way we did for the "All Posts". Then, we will add the Bootstrap formatting for the forms. A form is created as usual. In Bootstrap, each pairing of the labels and form inputs will be wrapped by a <div> with a class of form-group. Then, the input has a class of form-control. I also added a "Cancel" button that will go back to the post_list_view.

Your HTML should look like the following:

Post Create HTML
Figure 72. Post Create HTML

When we go to 'localhost:8000/posts/create', we should see the following in the browser:

Post Create in Browser
Figure 73. Post Create in Browser

We will do something similar with 'posts/update.html'. We will change our .html file to look like the following:

Post Update in HTML
Figure 74. Post Update in HTML

We also changed the link for our cancel to go back to the specific post_detail_view corresponding to the post that we are working on. This will look like the following:

Post Update in Browser
Figure 75. Post Update in Browser

Lastly, let’s change the 'posts/detail.html'. We should probably center name of the article, and make sure it has a top margin. Then, we should make sure to change the buttons to look nice. I changed the html to have Bootstrap classes and used the display-4 class to make the title look a little nicer.

The HTML will look like this now:

Post Detail in HTML
Figure 76. Post Detail in HTML

And then in the browser:

Post Detail in Browser
Figure 77. Post Detail in Browser

Lastly, let’s change our 'posts/delete.html' file. We will need to style our buttons, and make sure that the "Yes" button to confirm the deletion is red, so the user knows that it will delete the current post. Our HTML will now look like this:

Post Delete in HTML
Figure 78. Post Delete in HTML

And it looks like this in our browser:

Post Delete in Browser
Figure 79. Post Delete in Browser

Now, our project looks a lot better for the users of it. What if we have parts of our code that are repetitive? Well, we don’t want to repeat our self, so we will use Django’s include tool.

Including Other Files

Extending templates works great when you need to use certain elements on every page, and it is static across each file. However, what if you want to pick and choose when you use a certain snippet of code? Well, Django has a handy tool in its template language to do that.

{% include 'file_name.html' %}

If you write the preceding code in a Django template, it will "inject" the html from the file that you include. If we were to look at our code, a very large chunk of code is repeated - the form for creating and updating posts. So, let’s create a code snippet that we can inject into our other templates. Let’s put it in 'posts/snippets/form.html'. Then, copy the form from the 'posts/update.html' into the 'posts/snippets/form.html'.

It should look like this:

Form
Figure 80. Form

We want to be able to reuse this form on both the create and update pages, so we will need to move the {% 'posts:detail' id=post.id %}. This is because it is relying on the context which has 'post.id' in it. The post_create_view does not have any context, so we would get an error on the redirect. There are a couple ways we can do this. Let’s just remove the "Cancel" button to the outside of the 'form.html'. So, it will now look like this:

Form
Figure 81. Form without cancel

Then, we will move the <a> tag outside of the form and put them within the 'create.html' and 'update.html'. The "Cancel" button within the 'create.html' will redirect to the post_list_view and the "Cancel" button within the 'update.html' will redirect to the post_detail_view. So, we will include the file via {% include 'posts/snippets/form.html' %}. The 'posts/create.html' should look like this.

posts/create.html
Figure 82. posts/create.html

This is how we can reuse the form content. What about 'posts/update.html'? We will need to send a post to it. We do that using with in the {% include %} tag. It will look like this:

posts/update.html
Figure 83. posts/update.html

This is how we send variables to a form via the {% include %} tag. This feature is very picky when it comes to syntax, so you may have problems purely because of the syntax. You will now realize that the "Cancel" button is below the form. This is a quick fix by adding class="d-inline" to the <form> tag in 'posts/snippets/form.html'.

Now that we have the basic views set up, and we aren’t rewriting ode, we are able to add more styling to our app.

Advanced Django: Users

Django is great for setting up databases and such, but Django has a bunch of added things that really take your project to the next level. These functions include setting up Users in your model, which Django has plenty of different tools to make this easy. We will also look at ways to make your Django projects more secure, as well as signals, class based views and Django forms.

Django has a great framework for handling Users. It has a built in model, called User. There are a few ways to access this model, and we will look at the pros and cons of each. In our project, we want to add a user field to our blog posts so we know who the author is.

The User Model

Django has a built in model, the User model. It is just like the models we have seen in the past. When we want to create a new user, the implementation of this model will help us change the database. The User model is of class models.User. Every new instance of the User model will be another user. Each user has a few fields. These fields include the username, first_name, last_name, email, and password. There are several other fields that the User model has, but these are the main ones you will be using on a regular basis. If we wanted to create a User, we could go in the shell and do the following:

from django.contrib.auth import User
new_user = User.objects.create_user(username='myusername', email="test@test.com", password="password!123")

This will create a new user in the database. As a layer of safety, Django does not save the raw password in the database. It saves an encrypted version of it.

However, how should we organize the Users? I typically create a new app for that, called 'accounts'. So, let’s do that by going into the command line and typing

python manage.py startapp accounts

Then, we need to go into settings.py and add the accounts app to the INSTALLED_APPS. Once we have this, we can start writing our views. Remember, we already have a built in User model, so we will not need to create one in models.py.

Note
As you continue in your programming career, you will likely want to create your own User model. This can be done by starting off with the Django models and then changing them accordingly.

Now, let’s set up our views. Users are just like any other model - we will need to create a user, that is, a sign up feature. We will also need to be able to login and logout. Then, we want to be able to have a profile view so that you can view the individual user.

We can initially set up our 'accounts/views.py' as the following:

accounts/views.py
Figure 84. accounts/views.py

We have created our four main views. Also, note the imports in the template. This is using Django’s built in authentication methods. Not only does Django have the built in User model, but it also has methods to help the entire User authentication process. The methods include logging in, authenticating and logging out. We also have the ability to create a user using the User model manager, User.objects.create_user().

However, where does the User model come from? Typically, we would have imported the User model from 'accounts/models.py'. But, Django has the User model already created, so we will look at the various ways to import the User model.

Importing the User Class

We could directly import the User model. This is just like importing a normal model, but it will be a User model.

We do this with the following import:

from django.contrib.auth import User

This way we can reference the User model any time in the same way we would reference our Post model. However, this is not the ideal way to reference the User model. What if we end up extending the User model for our project? For example, if we make a class that inherits from User, we will want to reference that model. In Django, we can set which model we want to use for the User. So, we want to prepare for these instances.

get_user_model

The get_user_model function will do exactly what it says. It will return the User model that is activated in the project, and will default to django.contrib.auth.User. We implement it the following way:

from django.contrib.auth import get_user_model

User = get_user_model()

We first import the method get_user_model. Then, we define a variable, called User. In theory, we could name this anything, such as banana. The variable will just save the value that is returned from get_user_model.

AUTH_USER_MODEL

We can also import Django’s settings module and then reference the AUTH_USER_MODEL variable. Per Django’s documentation, it is best to use this when referring to a custom user model in foreign key relationships.

from django.conf import settings

User = settings.AUTH_USER_MODEL

A great thread on Stack Overflow discusses the differences between get_user_model and AUTH_USER_MODEL in more detail.

User Views

Now, let’s go back to the 'accounts/views.py' and import the User model via get_user_model(). We will start off with the user_create_view.

We will be creating users with three fields: username, email and password. So, let’s write the accounts/create.html template. This will be written as the following:

{% extends 'base.html' %}
{% block base_content %}
    <div class = "container pt-5">
        <div class = "display-4">
            Sign Up
        </div>
        <br/>
        <form method="POST">
            {% csrf_token %}
            <div class = "form-group">
                <label for = "username">Username</label>
                <input type="text" name="username" class = "form-control" required/>
            </div>
            <div class = "form-group">
                <label for = "email">Email</label>
                <input type="email" name="email" class = "form-control" required/>
            </div>
            <div class = "form-group">
                <label for = "password">Password</label>
                <input type="password" name="password" class = "form-control" required/>
            </div>
            <div class = "form-group">
                <label for = "confirm-password">Confirm Password</label>
                <input type="password" name="confirm-password" class = "form-control" required/>
            </div>
            <input type = "submit" value = "Sign Up" class = "btn btn-md btn-primary" />
        </form>
    </div>
{% endblock base_content %}

Remember - the class pt- is padding-top. We are using Bootstrap classes, form-group and form-control. We also added another input - confirm-password. This is so we can confirm there are no typos in their password. Also, we added the required attribute for each field. This is a special HTML attribute that allows us to check if the input is empty before it hits the server.

Next, let’s add the path to 'accounts/urls.py'. If you haven’t already, create the file 'urls.py' in your 'accounts' app. Then, let’s include the 'accounts.urls' in our 'myproject.urls' by adding the following path:

path('accounts/', include('accounts.urls', namespace='accounts'))

After adding all of our code into our 'accounts/urls.py', it will look like this:

from django.urls import path

from .views import user_create_view

app_name = 'accounts'

urlpatterns = [
    path('create/', user_create_view, name="create"),
]

So, whenever we use {% url %} in our templates to reference the 'accounts/create/', we will use {% url 'accounts:create' %}. When we visit it in our browser, it will resemble:

.localhost:8000/accounts/create
Figure 85. localhost:8000/accounts/create

This is exactly what we want. You can try to submit the form with bad email formatting or with one of the fields empty. Thanks to the HTML input types and the required attribute, a lot of our validation is done on the front end.

However, we cannot do all of our validation on the front end, so let’s go back to our 'accounts/views.py'. We need to do the following checks:

  1. See if the passwords equal each other

  2. See if the username is taken

  3. See if the email is already being used

So, within the if request.method == "POST": block, we can first check if the passwords equal. This way we can do the first check without having to check the database. In order to access the values, we can store the values in the inputs.

def user_create_view(request):
    context = {}
    if request.method == "POST":
        password = request.POST['password']
        confirm_password = request.POST['confirm-password']
        if password == confirm_password:
            #go to next check
            return render(request, 'accounts/create.html', context)
        else:
            context['error'] = "Passwords don't match"
            return render(request, 'accounts/create.html', context)
    else:
        return render(request, 'accounts/create.html', context)

Our user_create_view now has our first check. We also added a context variable to our output. We want to somehow send an error message if there is an issue, so this will be done in the context. We will define context['error'] in each block so that it is specific, and we know what exactly went wrong. That means we will have to add the error message code in our template as well. You can put this anywhere, but I typically put it right above the form, below the "Sign Up" title. We will use Bootstrap’s text-danger class.

{% if error %}
    <div class = "text-danger">
        {{error}}
    </div>
{% endif %}

We don’t want to include the code if the error key is empty, so we first check if it exists. If it does, then we inject the HTML.

We will next have to check if the username or email is already in the system. The logic is this: we will try to query the database and look for Users with the username/email that is given. If there is an error, that is: User.DoesNotExist, then we can create a new User.

So, let’s jump right in:

if password == confirm_password:
    username = request.POST['username']
    try:
        User.objects.get(username=username)
        context['error'] = "Username is taken"
        return render(request, 'accounts/create.html', context)
    except User.DoesNotExist:
        email = request.POST['email']
        try:
            User.objects.get(email=email)
            context['error'] = "Email already in system"
            return render(request, 'accounts/create.html', context)
        except User.DoesNotExist:
            user = User.objects.create_user(username=username, email=email, password=password)
            context['success'] = "Your Account is Created!"
            return render(request, 'accounts/create.html', context)

After we check if the passwords match, we try to get the user by the username. If we throw an exception, that is actually good, because we don’t have the username in the database. If we do not throw an exception, then our error message is "Username is taken". Then, we check for a user with the email, using the same strategy. We could have done both the email and username check in the same try block, but it makes it easier this way to see which field is causing the error.

If we create the user, then we have a new context item, success. This message will say "Your Account is Created!". We will not have both a success message and an error message, so we can rewrite our template like this:

{% if error %}
    <div class = "text-danger">
        {{error}}
    </div>
{% elif success %}
    <div class = "text-success">
        {{success}}
    </div>
{% endif %}

This uses Bootstrap’s text-success class, which is a green color. Now that we have this set up, try creating a user and make the passwords different.

Then, create a legitimate User instance and remember the username and email you type. You should see the following if it was done correctly:

User Success
Figure 86. User Success

Then, try to create another user with the same username/email. You should get error message if you cannot create it. We have officially created our user_create_view.

Now, let’s create our user_login_view. We first need to try to authenticate the User. This will actually verify that there is a user with the username and password provided. Then, we will login that user.

Let’s quickly create our template, 'accounts/login.html':

{% extends 'base.html' %}
{% block base_content %}
    <div class = "container pt-5">
        <div class = "display-4">
            Log In
        </div>
        {% if error %}
            <div class = "text-danger">
                {{error}}
            </div>
        {% elif success %}
            <div class = "text-success">
                {{success}}
            </div>
        {% endif %}
        <br />
        <form method="POST">
            {% csrf_token %}
            <div class = "form-group">
                <label for = "username">Username</label>
                <input type="text" name="username" class = "form-control" required/>
            </div>
            <div class = "form-group">
                <label for = "password">Password</label>
                <input type="password" name="password" class = "form-control" required/>
            </div>
            <input type = "submit" value = "Log In" class = "btn btn-md btn-primary" />
        </form>
    </div>
{% endblock base_content %}

Now, let’s work in our 'accounts/views.py'. So, we will import the authenticate and login functions from django.contrib.auth. Our import should look like this now:

from django.contrib.auth import authenticate, get_user_model, login

Authentication works by sending the username and login to the authenticate function. If there is no User with those credentials, it will return None. Otherwise, it will return the user.

So, our code will look like this:

def user_login_view(request):
    context = {}
    if request.method=="POST":
        username = request.POST['username']
        password = request.POST['password']
        user = authenticate(username=username, password=password)
        if user is not None:
            login(request, user)
            context['success'] = "You are logged in!"
            return render(request, 'accounts/login.html', context)
        else:
            context['error'] = "Invalid Login"
            return render(request, 'accounts/login.html', context)
    else:
        return render(request, 'accounts/login.html', context)

The login function takes in request as its first argument, then the user that has been authenticated as its second. If you try logging in with the user you just made, you should see a success message, otherwise, any other combination will result in an error. Lastly, we need to let the client call our function by adding the url to the 'accounts/urls.py'. Add the following path to your urlpatterns:

path('login/', user_login_view, name="login")

We have officially created user_login_view. Now, let’s do the user_logout_view.

We will need to place a logout button on each page, so it’s time to put a navbar in. Go to your 'base.html' file and put in a navbar above the {% block base_content %} and outside of the <div class = "container">. We will use Bootstrap’s collapsible navbar. Generally, you can just go to their website and copy the code you need and make any changes you need.

<nav class="navbar navbar-expand-lg navbar-light bg-light">
    <a class="navbar-brand" href="#">Django Blog</a>
    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#mainNav" aria-controls="mainNav" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
    </button>

    <div class="collapse navbar-collapse" id="mainNav">
        <ul class="navbar-nav mr-auto">
            <li class="nav-item active">
                <a class="nav-link" href="{% url 'posts:list' %}">All Posts</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="{% url 'posts:create' %}">Create Post</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="#">Log Out</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="{% url 'accounts:login' %}">Log In</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="{% url 'accounts:create' %}">Sign Up</a>
            </li>
        </ul>
    </div>
</nav>

We have added all of our User authentication buttons in our navbar. You may have noticed something - we will not need all of our authentication button at once. If nobody is logged in, then we will not need the "Log Out" button, and we don’t want them to be able to "Create Post".

If somebody is logged in, we don’t need the "Login" button or the "Sign Up" button. Luckily, Django has a very simple way to check if a user is authenticated in the template.

{% if user.is_authenticated %}
    <div>User is authenticated</div>
{% else %}
    <div>User is not authenticated</div>
{% endif %}

Now we can just plug this into the navbar. Use the following:

<ul class="navbar-nav mr-auto">
    <li class="nav-item active">
        <a class="nav-link" href="{% url 'posts:list' %}">All Posts</a>
    </li>
    {% if user.is_authenticated %}
        <li class="nav-item">
            <a class="nav-link" href="{% url 'posts:create' %}">Create Post</a>
        </li>
        <li class="nav-item">
            <a class="nav-link" href="#">Log Out</a>
        </li>
    {% else %}
        <li class="nav-item">
            <a class="nav-link" href="{% url 'accounts:login' %}">Log In</a>
        </li>
        <li class="nav-item">
            <a class="nav-link" href="{% url 'accounts:create' %}">Sign Up</a>
        </li>
    {% endif %}
</ul>

Depending on if you are logged in or not, you should see the "Log Out" and "Create Post" buttons or the "Log In" and "Sign Up" buttons.

Next, let’s finish up the user_logout_view. We need to first check is the user is authenticated. If the user is authenticated, then we will log out. If the user is not authenticated, and they just went to that page somehow by mistake, we will redirect to the login page. We will need to import the redirect function:

from django.shortcuts import render, redirect

We already have render imported. Now, let’s write the function.

def user_logout_view(request):
    if request.user.is_authenticated:
        logout(request)
        return redirect('posts:list')
    else:
        return redirect('accounts:login')

So, if the user is authenticated, it will log the user out. Then, it will redirect to the posts:list url. redirect works by taking in a string in the same way {% url %} does. Now we add a path to the accounts/urls.py. Remember to import user_logout_view.

path('logout/', user_logout_view, name="logout")

Now we can add the href attribute to the button in the navbar.

<li class="nav-item">
    <a class="nav-link" href="{% url 'accounts:logout' %}">Log Out</a>
</li>

Try testing it out. If you are not logged in, and you go to 'localhost:8000/accounts/logout', you should be redirected to the login screen. If you are logged in, and go to that URL click the 'Logout' button, you should be redirected to the post:list url, that is, post_list_view.

We have officially added all of our authentication views. Now we will be adding the user model as a foreign key in a model.

Adding the User as a Foreign Key

In our 'posts/models.py', we want to add an author field so that we can see who wrote the blog post. We will use the settings.AUTH_USER_MODEL approach.

This is when we introduce the idea of a Foreign Key. A Foreign Key relationship is a 'one-to-many' relationship. This means that there are two types of objects that can be related. But, there is a one way relationship.

Let’s look at the example of the Post model. Each instance of Post will have an author. An author is an instance of the User model. So, one author can have many different posts. However, every post can only have one author. This is a 'one-to-many' relationship in action.

Let’s add this in our model. We can change our 'posts/models.py' to look like this:

from django.db import models
from django.conf import settings

User = settings.AUTH_USER_MODEL

class Post(models.Model):
    title = models.CharField(max_length = 150)
    content = models.TextField()
    created_at = models.DateTimeField(auto_now_add = True)
    last_updated = models.DateTimeField(auto_now = True)
    author = models.ForeignKey(User, on_delete=models.CASCADE)

So, we import the settings and define our User. Then, we create a new field, author, that is a ForeignKey, pointing to the User model. In addition, we have the on_delete argument. You may want to go into the shell and delete all Posts, because we are adding a non-nullable field to an already existing instance. Or, when you migrate, you can just add a default value, that will be prompted on the migrate command. So, let’s perform our migrations:

python manage.py makemigrations

then,

python manage.py migrate

We will now have our author field added. How do we set the author, though when we are creating a model? We will now be updating our post views with our new author field.

Integrating the author field with our Views

First, let’s change post_create_view. We first should limit this view for those that are logged in. We don’t want anonymous users to be able to create a post. Django has a nifty way to do this. Go to your 'posts/views.py' and import the following:

from django.contrib.auth.decorators import login_required

This is a decorator that allows us to limit a view if someone is logged in. All you do once you import it, is add @login_required right on top of the view. So, change your post_create_view to look like this:

@login_required
def post_create_view(request):

Now, you will not be able to access that view unless you are logged in. And, through Django magic, if you are not logged in, it will redirect you to your login page. Give it a try. This is because it will redirect to 'accounts/login' by default. You can change this if you want to, but that is outside the context of this class.

Now that we are only allows those that are logged in to create a post, we can simply get the current user, and use that for the author field. The way we can do this is by accessing the User in the request object. We have already used this in the past, to check request.method and the request.POST. Now, we will will the request.user. This is the current user’s User instance. So, we can go back into our post_create_view and add the current user.

This would look like this:

if title and content:
    author = request.user
    post = Post.objects.create(title=title, content=content, author=author)
    return redirect('posts:detail', id=post.id)

Remember, this is within our post_create_view after we check if we have our title and content. If you are logged in, you will be able to test this out. Let’s first go the the 'posts/detail.html' template and add the author. Where we put the "Created" and "Updated" fields.

<p>Created: {{post.created_at}} | Updated: {{post.last_updated}} | Written by: {{post.author.username}}</p>

Next, go to 'localhost:8000/posts/create' and create a new post. When it is redirected, it should go to the 'posts:detail' view and say the username. My username for the user is 'username', so it will look like this:

Post Detail with Author
Figure 87. Post Detail with Author

Now we need to think about how to change the rest of the views now that we have users. Any views that change the database will need the @login_required tag.

@login_required
def post_update_view(request, id):

@login_required
def post_delete_view(request, id):

These two views will require a valid login. However, we also want to make sure that the only person that can change the post is the author. So, we can make a new template in our 'posts' folder, called 'posts/unauthorized.html'. It can say anything, but I put the following:

{% extends 'base.html' %}
{% block base_content %}
<div class = "row">
    <h1>UNAUTHORIZED</h1>
</div>
{% endblock base_content %}

So now in our post_update_view and post_delete_view, we will first check if the currently logged in user, request.user is the same as the author.

@login_required
def post_update_view(request, id):
    post = Post.objects.filter(id=id).first()
    context = { 'post': post }
    if request.user == post.author:
        if request.method == "POST":
            updated_title = request.POST['post-title']
            updated_content = request.POST['post-content']
            if updated_title and updated_content:
                updated_post = Post.objects.filter(id=id).update(title = updated_title, content = updated_content)
                return redirect('posts:detail', id=post.id)
            else:
                context['error'] = "Both Title and Content are necessary!"
                return render(request, 'posts/update.html', context = context)
        else:
            return render(request, 'posts/update.html', context = context)
    else:

Now, if we were to create another user, and try to click the 'Edit' button on a certain Post instance, we will see the 'posts/unauthorized.html' template. There are a few different ways to do this. We could also redirect to the login view, or we could make another view entirely, at let’s say, '/posts/unauthorized'. This is just a simple way. We can do the same for the post_update_view.

@login_required
def post_delete_view(request, id):
    post = Post.objects.filter(id=id).first()
    context = { 'post': post }
    if request.user == post.author:
        if request.method == "POST":
            post = Post.objects.filter(id=id).delete()
            return redirect('posts:list')
        else:
            return render(request, 'posts/delete.html', context = context)
    else:
        return render(request, 'posts/unauthorized.html')

Notice that the @login_required tag is now irrelevant for the post_update_view and post_delete_view. This is because we are doing a check for the current user anyways, so we won’t be able to see the view if we are not logged in as the current user. So, let’s delete it for these two views.

Lastly, let’s see how this affects our templates. In our 'posts/detail.html' template, we only want to show the "Edit" and "Delete" button if the current user is the author. In our 'posts/detail.html', we should change our code with the following if statement:

{% if user == post.author %}
    <a href="{% url 'posts:update' id=post.id %}" class="btn btn-md btn-success">Edit</a>
    <a href="{% url 'posts:delete' id=post.id %}" class="btn btn-md btn-warning">Delete</a>
{% endif %}

We have changed all of our views and models to include users. As you have seen, Django does a lot to help with this.

Class Based Views