---
# System prepended metadata

title: Django
tags: [WEB50x]

---

# Django

###### tags: `WEB50x`


<main class="col-md" style="margin-bottom: 70px; margin-top: 58px;">


<ul id="markdown-toc">
  <li><a href="#introduction" id="markdown-toc-introduction">Introduction</a></li>
  <li><a href="#web-applications" id="markdown-toc-web-applications">Web Applications</a></li>
  <li><a href="#http" id="markdown-toc-http">HTTP</a></li>
  <li><a href="#django" id="markdown-toc-django">Django</a></li>
  <li><a href="#routes" id="markdown-toc-routes">Routes</a></li>
  <li><a href="#templates" id="markdown-toc-templates">Templates</a>    <ul>
      <li><a href="#conditionals" id="markdown-toc-conditionals">Conditionals:</a></li>
      <li><a href="#styling" id="markdown-toc-styling">Styling</a></li>
    </ul>
  </li>
  <li><a href="#tasks" id="markdown-toc-tasks">Tasks</a></li>
  <li><a href="#forms" id="markdown-toc-forms">Forms</a>    <ul>
      <li><a href="#django-forms" id="markdown-toc-django-forms">Django Forms</a></li>
    </ul>
  </li>
  <li><a href="#sessions" id="markdown-toc-sessions">Sessions</a></li>
</ul>

<a data-id="" id="introduction" style="top: -58px;"></a><h2><a data-id="" href="#introduction">Introduction</a></h2>

<ul class="fa-ul">
  <li data-marker="*"><span class="fa-li"><i class="fas fa-square"></i></span>So far, we’ve discussed how to build simple web pages using HTML and CSS, and how to use Git and GitHub in order to keep track of changes to our code and collaborate with others. We also familiarized ourselves with the Python programming language.</li>
  <li data-marker="*"><span class="fa-li"><i class="fas fa-square"></i></span>Today, we’ll work on using Python’s <code class="language-plaintext highlighter-rouge">Django</code> framework in order to create dynamic applications.</li>
</ul>

<a data-id="" id="web-applications" style="top: -58px;"></a><h2><a data-id="" href="#web-applications">Web Applications</a></h2>

<p>So far, all of the web applications we’ve written have been <strong>static</strong>. This means that every single time we open that web page, it looks exactly the same. Many websites we visit every day, however, change every time we visit them. If you visit the websites of the <a href="https://www.nytimes.com/">New York Times</a> or <a href="https://www.facebook.com/">Facebook</a>, for example, you’ll most likely see different things today than you will tomorrow. For large sites like those, it would be unreasonable for employees to have to manually edit a large HTML file every time a change is made, which is where <strong>dynamic</strong> websites can be extremely useful. A dynamic website is one that takes advantage of a programming language (such as Python) to dynamically generate HTML and CSS files. During this lecture, we’ll learn how to create our first dynamic applications.</p>

<a data-id="" id="http" style="top: -58px;"></a><h2><a data-id="" href="#http">HTTP</a></h2>

<p>HTTP, or HyperText Transfer Protocol, is a widely-accepted protocol for how messages are transfered back and forth across the internet. Typically, information online is passed between a client (user) and a server.
<img src="https://cs50.harvard.edu/web/2020/notes/3/images/client_server.png" alt="Client and Server">

<p>In this protocol, the client will send a <strong>request</strong> to the server, that might look something like the one below. In the example below, <code class="language-plaintext highlighter-rouge">GET</code> is simply a type of request, one of three we’ll discuss in this course. The <code class="language-plaintext highlighter-rouge">/</code> typically indicates that we’re looking for the website’s home page, and the three dots indicate that we could be passing in more information as well.
<img src="https://cs50.harvard.edu/web/2020/notes/3/images/request.png" alt="Request"></p>

<p>After receiving a request, a server will then send back an HTTP response, which might look something like the one below. Such a response will include the HTTP version, a status code (200 means OK), a description of the content, and then some additional information.
<img src="https://cs50.harvard.edu/web/2020/notes/3/images/response.png" alt="Response"></p>

<p>200 is just one of many status codes, some of which you may have seen in the past:
<img src="https://cs50.harvard.edu/web/2020/notes/3/images/codes.png" alt="Codes"></p>

<a data-id="" id="django" style="top: -58px;"></a><h2><a data-id="" href="#django">Django</a></h2>

<p><a href="https://www.djangoproject.com/">Django</a> is a Python-based web framework that will allow us to write Python code that dynamically generates HTML and CSS. The advantage to using a framework like Django is that a lot of code is already written for us that we can take advantage of.</p>

<ul class="fa-ul">
  <li data-marker="*"><span class="fa-li"><i class="fas fa-square"></i></span>To get started, we’ll have to install Django, which means you’ll also have to <a href="https://pip.pypa.io/en/stable/installing/">install pip</a> if you haven’t already done so.</li>
  <li data-marker="*"><span class="fa-li"><i class="fas fa-square"></i></span>Once you have Pip installed, you can run <code class="language-plaintext highlighter-rouge">pip3 install Django</code> in your terminal to install Django.</li>
</ul>

<p>After installing Django, we can go through the steps of creating a new Django project:</p>
<ol>
  <li>Run <code class="language-plaintext highlighter-rouge">django-admin startproject PROJECT_NAME</code> to create a number of starter files for our project.</li>
  <li>Run <code class="language-plaintext highlighter-rouge">cd PROJECT_NAME</code> to navigate into your new project’s directory.</li>
  <li>Open the directory in your text editor of choice. You’ll notice that some files have been created for you. We won’t need to look at most of these for now, but there are three that will be very important from the start:
    <ul class="fa-ul">
      <li data-marker="*"><span class="fa-li"><i class="fas fa-square"></i></span><code class="language-plaintext highlighter-rouge">manage.py</code> is what we use to execute commands on our terminal. We won’t have to edit it, but we’ll use it often.</li>
      <li data-marker="*"><span class="fa-li"><i class="fas fa-square"></i></span><code class="language-plaintext highlighter-rouge">settings.py</code> contains some important configuration settings for our new project. There are some default settings, but we may wish to change some of them from time to time.</li>
      <li data-marker="*"><span class="fa-li"><i class="fas fa-square"></i></span><code class="language-plaintext highlighter-rouge">urls.py</code> contains directions for where users should be routed after navigating to a certain URL.</li>
    </ul>
  </li>
  <li>Start the project by running <code class="language-plaintext highlighter-rouge">python manage.py runserver</code>. This will open a development server, which you can access by visiting the URL provided. This development server is being run locally on your machine, meaning other people cannot access your website. This should bring you to a default landing page:
<img src="https://cs50.harvard.edu/web/2020/notes/3/images/landing.png" alt="Landing Page"></li>
  <li>Next, we’ll have to create an application. Django projects are split into one or more <strong>applications</strong>. Most of our projects will only require one application, but larger sites can make use of this ability to split a site into multiple apps. To create an application, we run <code class="language-plaintext highlighter-rouge">python manage.py startapp APP_NAME</code>. This will create some additional directories and files that will be useful shortly, including <code class="language-plaintext highlighter-rouge">views.py</code>.</li>
  <li>Now, we have to install our new app. To do this, we go to <code class="language-plaintext highlighter-rouge">settings.py</code>, scroll down to the list of <code class="language-plaintext highlighter-rouge">INSTALLED_APPS</code>, and add the name of our new application to this list.
<img src="https://cs50.harvard.edu/web/2020/notes/3/images/installed.png" alt="installed apps"></li>
</ol>

<a data-id="" id="routes" style="top: -58px;"></a><h2><a data-id="" href="#routes">Routes</a></h2>

<p>Now, in order to get started with our application:</p>
<ol>
  <li>
    <p>Next, we’ll navigate to <code class="language-plaintext highlighter-rouge">views.py</code>. This file will contain a number of different views, and we can think of a view for now as one page the user might like to see. To create our first view, we’ll write a function that takes in a <code class="language-plaintext highlighter-rouge">request</code>. For now, we’ll simply return an <code class="language-plaintext highlighter-rouge">HttpResponse</code> (A very simple response that includes a response code of 200 and a string of text that can be displayed in a web browser) of “Hello, World”. In order to do this, we have include <code class="language-plaintext highlighter-rouge">from django.http import HttpResponse</code>. Our file now looks like:</p>

```python=
 from django.shortcuts import render
 from django.http import HttpResponse

 # Create your views here.

 def index(request):
     return HttpResponse("Hello, world!")
      
```

  </li>
  <li>Now, we need to somehow associate this view we have just created with a specific URL. To do this, we’ll create another file called <code class="language-plaintext highlighter-rouge">urls.py</code> in the same directory as <code class="language-plaintext highlighter-rouge">views.py</code>. We already have a <code class="language-plaintext highlighter-rouge">urls.py</code> file for the whole project, but it is best to have a separate one for each individual app.</li>
  <li>Inside our new <code class="language-plaintext highlighter-rouge">urls.py</code>, we’ll create a list of url patterns that a user might visit while using our website. In order to do this:
    <ol>
      <li>We have to make some imports: <code class="language-plaintext highlighter-rouge">from django.urls import path</code> will give us the ability to reroute URLSs, and <code class="language-plaintext highlighter-rouge">from . import views</code> will import any functions we’ve created in <code class="language-plaintext highlighter-rouge">views.py</code>.</li>
      <li>Create a list called <code class="language-plaintext highlighter-rouge">urlpatterns</code></li>
      <li>For each desired URL, add an item to the <code class="language-plaintext highlighter-rouge">urlpatterns</code> list that contains a call to the <code class="language-plaintext highlighter-rouge">path</code> function with two or three arguments: A string representing the URL path, a function from <code class="language-plaintext highlighter-rouge">views.py</code> that we wish to call when that URL is visited, and (optionally) a name for that path, in the format <code class="language-plaintext highlighter-rouge">name="something"</code>. For example, here’s what our simple app looks like now:</li>
    </ol>

```python=
from django.urls import path
 from . import views

 urlpatterns = [
     path("", views.index, name="index")
 ]
```
  </li>
  <li>
    <p>Now, we’ve created a <code class="language-plaintext highlighter-rouge">urls.py</code> for this specific application, and it’s time to edit the <code class="language-plaintext highlighter-rouge">urls.py</code> created for us for the entire project. When you open this file, you should see that there’s already a path called <code class="language-plaintext highlighter-rouge">admin</code> which we’ll go over in later lectures. We want to add another path for our new app, so we’ll add an item to the <code class="language-plaintext highlighter-rouge">urlpatterns</code> list. This follows the same pattern as our earlier paths, except instead of adding a function from <code class="language-plaintext highlighter-rouge">views.py</code> as our second argument, we want to be able to include <em>all</em> of the paths from the <code class="language-plaintext highlighter-rouge">urls.py</code> file within our application. To do this, we write: <code class="language-plaintext highlighter-rouge">include("APP_NAME.urls")</code>, where <code class="language-plaintext highlighter-rouge">include</code> is a function we gain access to by also importing <code class="language-plaintext highlighter-rouge">include</code> from <code class="language-plaintext highlighter-rouge">django.urls</code> as shown in the <code class="language-plaintext highlighter-rouge">urls.py</code> below:</p>
      
```python=
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('hello/', include("hello.urls"))
]
```
  </li>
  <li>By doing this, we’ve specified that when a user visits our site, and then in the search bar adds <code class="language-plaintext highlighter-rouge">/hello</code> to the URL, they’ll be redirected to the paths inside of our new application.</li>
</ol>

<p>Now, when I start my application using <code class="language-plaintext highlighter-rouge">python manage.py runserver</code> and visit the url provided, I’m met with this screen:
<img src="https://cs50.harvard.edu/web/2020/notes/3/images/404.png" alt="wrong url">
But this is because we have only defined the URL <code class="language-plaintext highlighter-rouge">localhost:8000/hello</code>, but we haven’t defined the URL <code class="language-plaintext highlighter-rouge">localhost:8000</code> with nothing added to the end. So, when I add <code class="language-plaintext highlighter-rouge">/hello</code> to the URL in my search bar:
<img src="https://cs50.harvard.edu/web/2020/notes/3/images/helloworld.png" alt="Hello, world">
Now that we’ve had some success, let’s go over what just happened to get us to that point:</p>
<ol>
  <li>When we accessed the URL <code class="language-plaintext highlighter-rouge">localhost:8000/hello/</code>, Django looked at what came after the base URL (<code class="language-plaintext highlighter-rouge">localhost:8000/</code>) and went to our project’s <code class="language-plaintext highlighter-rouge">urls.py</code> file and searched for a pattern that matched <code class="language-plaintext highlighter-rouge">hello</code>.</li>
  <li>It found that extension because we defined it, and saw that when met with that extension, it should <code class="language-plaintext highlighter-rouge">include</code> our <code class="language-plaintext highlighter-rouge">urls.py</code> file from within our application.</li>
  <li>Then, Django ignored the parts of the URL it has already used in rerouting (<code class="language-plaintext highlighter-rouge">localhost:8000/hello/</code>, or all of it) and looked inside our other <code class="language-plaintext highlighter-rouge">urls.py</code> file for a pattern that matches the remaining part of the URL.</li>
  <li>It found that our only path so far (<code class="language-plaintext highlighter-rouge">""</code>) matched what was left of the URL, and so it directed us to the function from <code class="language-plaintext highlighter-rouge">views.py</code> associated with that path.</li>
  <li>Finally, Django ran that function within <code class="language-plaintext highlighter-rouge">views.py</code>, and returned the result (<code class="language-plaintext highlighter-rouge">HttpResponse("Hello, world!")</code>) to our web browser.</li>
</ol>

<p>Now, if we want to, we can change the <code class="language-plaintext highlighter-rouge">index</code> function within <code class="language-plaintext highlighter-rouge">views.py</code> to return anything we want it to! We could even keep track of variables and do calculations within the function before eventually returning something.</p>

<p>Now, let’s take a look at how we can add more than one view to our application. We can follow many of the same steps within our application to create pages that say hello to Brian and David.</p>

<p>Inside <code class="language-plaintext highlighter-rouge">views.py</code>:</p>

```python=
from django.shortcuts import render
from django.http import HttpResponse

# Create your views here.

def index(request):
    return HttpResponse("Hello, world!")

def brian(request):
    return HttpResponse("Hello, Brian!")

def david(request):
    return HttpResponse("Hello, David!")
```




<p>Inside <code class="language-plaintext highlighter-rouge">urls.py</code> (within our application)</p>

```python=
from django.urls import path
from . import views

urlpatterns = [
    path("", views.index, name="index"),
    path("brian", views.brian, name="brian"),
    path("david", views.david, name="david")
]
```

<p>Now, our site remains unchanged when we visit <code class="language-plaintext highlighter-rouge">localhost:8000/hello</code>, but we get different pages when we add <code class="language-plaintext highlighter-rouge">brian</code> or <code class="language-plaintext highlighter-rouge">david</code> to the URL:
<img src="https://cs50.harvard.edu/web/2020/notes/3/images/brian.png" alt="Brian">
<img src="https://cs50.harvard.edu/web/2020/notes/3/images/david.png" alt="David"></p>

<p>Many sites are parameterized by items included in the URL. For example, going to <a href="https://twitter.com/cs50">www.twitter.com/cs50</a> will show you all of CS50’s tweets, and going to <a href="https://github.com/cs50">www.github.com/cs50</a> will bring you to CS50’s GitHub page. You can even find your own public GitHub repositories by navigating to <code class="language-plaintext highlighter-rouge">www.github.com/YOUR_USERNAME</code>!</p>

<p>In thinking about how this is implemented, it seems impossible that sites like GitHub and Twitter would have an individual URL path for each of its users, so let’s look into how we could make a path that’s a bit more flexible. We’ll start by adding a more general function, called <code class="language-plaintext highlighter-rouge">greet</code>, to <code class="language-plaintext highlighter-rouge">views.py</code>:</p>


```python=
def greet(request, name):
    return HttpResponse(f"Hello, {name}!")
```

<p>This function takes in not only a request, but also an additional argument of a user’s name, and then returns a custom HTTP Response based on that name. Next, we have to create a more flexible path in <code class="language-plaintext highlighter-rouge">urls.py</code>, which could look somehting like this:</p>

```python=
path("<str:name>", views.greet, name="greet")

```

<p>This is some new syntax, but essentially what’s going on here is we’re no longer looking for a specific word or name in the URL, but any string that a user might enter. Now, we can try the site out with a few other URLs:
<img src="https://cs50.harvard.edu/web/2020/notes/3/images/harry.png" alt="harry">
<img src="https://cs50.harvard.edu/web/2020/notes/3/images/connor.png" alt="connor"></p>

<p>I can even make these look a little bit nicer, by augmenting the <code class="language-plaintext highlighter-rouge">greet</code> function to utilize Python’s <code class="language-plaintext highlighter-rouge">capitalize</code> function that capitalizes a string:</p>


```python=
def greet(request, name):
    return HttpResponse(f"Hello, {name.capitalize()}!")
```

<p><img src="https://cs50.harvard.edu/web/2020/notes/3/images/harryc.png" alt="Harry">
<img src="https://cs50.harvard.edu/web/2020/notes/3/images/connorc.png" alt="Connor"></p>

<p>This is a great illustration of how any functionality we have in Python can be used in Django before being returned.</p>

<a data-id="" id="templates" style="top: -58px;"></a><h2><a data-id="" href="#templates">Templates</a></h2>

<p>So far, our HTTP Responses, have been only text, but we can include any HTML elements we want to! For example, I could decide to return a blue header instead of just the text in our <code class="language-plaintext highlighter-rouge">index</code> function:</p>


```python=
def index(request):
    return HttpResponse("<h1 style=\"color:blue\">Hello, world!</h1>")
```

<p><img src="https://cs50.harvard.edu/web/2020/notes/3/images/bluehello.png" alt="Blue"></p>

<p>It would get very tedious to write an entire HTML page within <code class="language-plaintext highlighter-rouge">views.py</code>. It would also constitute bad design, as we want to keep separate parts of our project in separate files whenever possible.</p>

<p>This is why we’ll now introduce <a href="https://docs.djangoproject.com/en/3.0/topics/templates/">Django’s templates</a>, which will allow us to write HTML and CSS in separate files and render those files using Django. The syntax we’ll use for rendering a template looks like this:</p>

```python=
def index(request):
    return render(request, "hello/index.html")

```

<p>Now, we’ll need to create that template. To do this, we’ll create a folder called <code class="language-plaintext highlighter-rouge">templates</code> inside our app, then create a folder called <code class="language-plaintext highlighter-rouge">hello</code> (or whatever our app’s name is) within that, and then add a file called <code class="language-plaintext highlighter-rouge">index.html</code>.</p>

<p><img src="https://cs50.harvard.edu/web/2020/notes/3/images/files.png" alt="Files"></p>

<p>Next, we’ll add whatever we want to that new file:</p>


```htmlmixed=
<!DOCTYPE html>
<html lang="en">
    <head>
        <title>Hello</title>
    </head>
    <body>
        <h1>Hello, World!</h1>
    </body>
</html>
```

<p>Now, when we visit the main page of our application, we can see the header and title have been updated:
<img src="https://cs50.harvard.edu/web/2020/notes/3/images/template0.png" alt="template0"></p>

<p>In addition to writing some static HTML pages, we can also use <a href="https://docs.djangoproject.com/en/3.0/ref/templates/language/">Django’s templating language</a> to change the content of our HTML files based on the URL visited. Let’s try it out by changing our <code class="language-plaintext highlighter-rouge">greet</code> function from earlier:</p>

```python=
def greet(request, name):
    return render(request, "hello/greet.html", {
        "name": name.capitalize()
    })
```

<p>Notice that we passed a third argument into the <code class="language-plaintext highlighter-rouge">render</code> function here, one that is known as the <strong>context</strong>. In this context, we can provide information that we would like to have available within our HTML files. This context takes the form of a Python dictionary. Now, we can create a <code class="language-plaintext highlighter-rouge">greet.html</code> file:</p>

```htmlmixed=
<!DOCTYPE html>
<html lang="en">
    <head>
        <title>Hello</title>
    </head>
    <body>
        <h1>Hello, {{ name }}!</h1>
    </body>
</html>
```

<p>You’ll noticed that we used some new syntax: double curly brackets. This syntax allows us to access variables that we’ve provided in the <code class="language-plaintext highlighter-rouge">context</code> argument. Now, when we try it out:
<img src="https://cs50.harvard.edu/web/2020/notes/3/images/template1.png" alt="Template 1">
<img src="https://cs50.harvard.edu/web/2020/notes/3/images/template2.png" alt="Template 2"></p>

<p>Now, we’ve seen how we can modify our HTML templates based on the context we provide. However, the Django templating language is even more powerful than that, so let’s take a look at a few other ways it can be helpful:</p>

<a data-id="" id="conditionals" style="top: -58px;"></a><h3><a data-id="" href="#conditionals">Conditionals:</a></h3>

<p>We may want to change what is displayed on our website depending on some conditions. For example, if you visit the site <a href="https://www.isitchristmas.com">www.isitchristmas.com</a>, you’ll probably be met with a page that looks like this:
<img src="https://cs50.harvard.edu/web/2020/notes/3/images/isitno.png" alt="no">
But this website will change on Christmas day, when the website will say <strong>YES</strong>. To make something like this for ourselves, let’s try creating a similar application, where we check whether or not it is New Year’s Day. Let’s create a new app to do so, recalling our process for creating a new app:</p>
<ol>
  <li>run <code class="language-plaintext highlighter-rouge">python manage.py startapp newyear</code> in the terminal.</li>
  <li>Edit <code class="language-plaintext highlighter-rouge">settings.py</code>, adding “newyear” as one of our <code class="language-plaintext highlighter-rouge">INSTALLED_APPS</code></li>
  <li>Edit our project’s <code class="language-plaintext highlighter-rouge">urls.py</code> file, and include a path similar to the one we created for the <code class="language-plaintext highlighter-rouge">hello</code> app:</li>
</ol>

```python=
path('newyear/', include("newyear.urls"))

```

<ol>
  <li>Create another <code class="language-plaintext highlighter-rouge">urls.py</code> file within our new app’s directory, and update it to include a path similar to the index path in <code class="language-plaintext highlighter-rouge">hello</code>:</li>
</ol>

```python=
from django.urls import path
from . import views

urlpatterns = [
    path("", views.index, name="index"),
]
```

<ol>
  <li>Create an index function in <code class="language-plaintext highlighter-rouge">views.py</code>.</li>
</ol>

<p>Now that we’re set up with our new app, let’s figure out how to check whether or not it’s New Year’s Day. To do this, we can import Python’s <a href="https://docs.python.org/3/library/datetime.html">datetime</a> module. To get a sense for how this module works, we can look at the <a href="https://docs.python.org/3/library/datetime.html">documentation</a>, and then test it outside of Django using the Python interpreter.</p>
<ul class="fa-ul">
  <li data-marker="*"><span class="fa-li"><i class="fas fa-square"></i></span>The <strong>Python interpreter</strong> is a tool we can use to test out small chunks of Python code. To use this, run <code class="language-plaintext highlighter-rouge">python</code> in your terminal, and then you’ll be able to type and run Python code within your terminal. When you’re done using the interpreter, run <code class="language-plaintext highlighter-rouge">exit()</code> to leave.
<img src="https://cs50.harvard.edu/web/2020/notes/3/images/datetime.png" alt="interpreter"></li>
  <li data-marker="*"><span class="fa-li"><i class="fas fa-square"></i></span>We can use this knowledge to construct a boolean expression that will evaluate to True if and only if today is New Year’s Day: <code class="language-plaintext highlighter-rouge">now.day == 1 and now.month == 1</code></li>
  <li data-marker="*"><span class="fa-li"><i class="fas fa-square"></i></span>Now that we have an expression we can use to evaluate whether or not it’s New Year’s Day, we can update our index function in <code class="language-plaintext highlighter-rouge">views.py</code>:</li>
</ul>

```python=
def index(request):
    now = datetime.datetime.now()
    return render(request, "newyear/index.html", {
        "newyear": now.month == 1 and now.day == 1
    })
```

<p>Now, let’s create our <code class="language-plaintext highlighter-rouge">index.html</code> template. We’ll have to again create a new folder called <code class="language-plaintext highlighter-rouge">templates</code>, a folder within that called <code class="language-plaintext highlighter-rouge">newyear</code>, and a file within that called <code class="language-plaintext highlighter-rouge">index.html</code>. Inside that file, we’ll write something like this:</p>

```htmlmixed=
<!DOCTYPE html>
<html lang="en">
    <head>
        <title>Is it New Year's?</title>
    </head>
    <body>
        {% if newyear %}
            <h1>YES</h1>
        {% else %}
            <h1>NO</h1>
        {% endif %}
    </body>
</html>
```

<p>In the code above, notice that when we wish to include logic in our HTML files, we use <code class="language-plaintext highlighter-rouge">{%</code> and <code class="language-plaintext highlighter-rouge">%}</code> as opening and closing tags around logical statements. Also note that Django’s formatting language requires you to include an ending tag indicating that we are done with our <code class="language-plaintext highlighter-rouge">if-else</code> block. Now, we can open up to our page to see:</p>

<p><img src="https://cs50.harvard.edu/web/2020/notes/3/images/no.png" alt="No"></p>

<p>Now, to get a better idea of what’s going on behind the scenes, let’s inspect the element of this page:</p>

<p><img src="https://cs50.harvard.edu/web/2020/notes/3/images/source.png" alt="Source"></p>

<p>Notice that the HTML that is actually being sent to your web browser includes only the NO header, meaning that Django is using the HTML template we wrote to create a new HTML file, and then sending it to our web browser. If we cheat a little bit and make sure that our condition is always true, we see that the opposite case is filled:</p>

```python=
def index(request):
    now = datetime.datetime.now()
    return render(request, "newyear/index.html", {
        "newyear": True
    })
```

<p><img src="https://cs50.harvard.edu/web/2020/notes/3/images/yes.png" alt="Yes">
<img src="https://cs50.harvard.edu/web/2020/notes/3/images/source0.png" alt="Source 0"></p>

<a data-id="" id="styling" style="top: -58px;"></a><h3><a data-id="" href="#styling">Styling</a></h3>

<p>If we want to add a CSS file, which is a <em>static</em> file because it doesn’t change, we’ll first create a folder called <code class="language-plaintext highlighter-rouge">static</code>, then create a <code class="language-plaintext highlighter-rouge">newyear</code> folder within that, and then a <code class="language-plaintext highlighter-rouge">styles.css</code> file within that. In this file, we can add any styling we wish just as we did in the first lecture:</p>

```css=
h1 {
    font-family: sans-serif;
    font-size: 90px;
    text-align: center;
}
```

<p>Now, to include this styling in our HTML file, we add the line <code class="language-plaintext highlighter-rouge">{% load static %}</code> to the top of our HTML template, which signals to Django that we wish to have access to the files in our <code class="language-plaintext highlighter-rouge">static</code> folder. Then, rather than hard-coding the link to a stylesheet as we did before, we’ll use some Django-specific syntax:</p>

```htmlmixed=
<link rel="stylesheet" href="{% static 'newyear/styles.css' %}">

```

<p>Now, if we restart the server, we can see that the styling changes were in fact applied:
<img src="https://cs50.harvard.edu/web/2020/notes/3/images/bigno.png" alt="big no"></p>

<a data-id="" id="tasks" style="top: -58px;"></a><h2><a data-id="" href="#tasks">Tasks</a></h2>

<p>Now, let’s take what we’ve learned so far and apply it to a mini-project: creating a TODO list.
Let’s start by, once again, creating a new app:</p>
<ol>
  <li>run <code class="language-plaintext highlighter-rouge">python manage.py startapp tasks</code> in the terminal.</li>
  <li>Edit <code class="language-plaintext highlighter-rouge">settings.py</code>, adding “tasks” as one of our <code class="language-plaintext highlighter-rouge">INSTALLED_APPS</code></li>
  <li>
    <p>Edit our project’s <code class="language-plaintext highlighter-rouge">urls.py</code> file, and include a path similar to the one we created for the <code class="language-plaintext highlighter-rouge">hello</code> app:</p>

```python=
 path('tasks/', include("tasks.urls"))

```
    
  </li>
  <li>
    <p>Create another <code class="language-plaintext highlighter-rouge">urls.py</code> file within our new app’s directory, and update it to include a path similar to the index path in <code class="language-plaintext highlighter-rouge">hello</code>:</p>
      
```python=
from django.urls import path
from . import views

urlpatterns = [
     path("", views.index, name="index"),
 ]
```
   
  </li>
  <li>Create an index function in <code class="language-plaintext highlighter-rouge">views.py</code>.</li>
</ol>

<p>Now, let’s begin by attempting to simply create a list of tasks and then display them to a page. Let’s create a Python list at the top of <code class="language-plaintext highlighter-rouge">views.py</code> where we’ll store our tasks. Then, we can update our <code class="language-plaintext highlighter-rouge">index</code> function to render a template, and provide our newly-created list as context.</p>



```python=
from django.shortcuts import render

tasks = ["foo", "bar", "baz"]

# Create your views here.
def index(request):
    return render(request, "tasks/index.html", {
        "tasks": tasks
    })
```

<p>Now, let’s work on creating our template HTML file:</p>

```htmlmixed=
<!DOCTYPE html>
<html lang="en">
    <head>
        <title>Tasks</title>
    </head>
    <body>
        <ul>
            {% for task in tasks %}
                <li>{{ task }}</li>
            {% endfor %}
        </ul>
    </body>
</html>

```

<p>Notice here that we are able to loop over our tasks using syntax similar to our conditionals from earlier, and also similar to a Python loop from Lecture 2. When we go to the tasks page now, we can see our list being rendered:
<img src="https://cs50.harvard.edu/web/2020/notes/3/images/tasks0.png" alt="tasks0"></p>

<a data-id="" id="forms" style="top: -58px;"></a><h2><a data-id="" href="#forms">Forms</a></h2>

<p>Now that we can see all of our current tasks as a list, we may want to be able to add some new tasks. To do this we’ll start taking a look at using forms to update a web page. Let’s begin by adding another function to <code class="language-plaintext highlighter-rouge">views.py</code> that will render a page with a form for adding a new task:</p>

```python=
# Add a new task:
def add(request):
    return render(request, "tasks/add.html")
```

<p>Next, make sure to add another path to <code class="language-plaintext highlighter-rouge">urls.py</code>:</p>


```python=
path("add", views.add, name="add")

```

<p>Now, we’ll create our <code class="language-plaintext highlighter-rouge">add.html</code> file, which is fairly similar to <code class="language-plaintext highlighter-rouge">index.html</code>, except that in the body we’ll include a form rather than a list:</p>


```htmlmixed=
<!DOCTYPE html>
<html lang="en">
    <head>
        <title>Tasks</title>
    </head>
    <body>
        <h1>Add Task:</h1>
        <form action="">
            <input type="text", name="task">
            <input type="submit">
        </form>
    </body>
</html>

```

<p>However, what we’ve just done isn’t necessarily the best design, as we’ve just repeated the bulk of that HTML in two different files. Django’s templating language gives us a way to eliminate this poor design: <a href="https://tutorial.djangogirls.org/en/template_extending/">template inheritance</a>. This allows us to create a <code class="language-plaintext highlighter-rouge">layout.html</code> file that will contain the general structure of our page:</p>


```htmlmixed=
<!DOCTYPE html>
<html lang="en">
    <head>
        <title>Tasks</title>
    </head>
    <body>
        {% block body %}
        {% endblock %}
    </body>
</html>

```

<p>Notice that we’ve again used <code class="language-plaintext highlighter-rouge">{%...%}</code> to denote some sort of non-HTML logic, and in this case, we’re telling Django to fill this “block” with some text from another file. Now, we can alter our other two HTML files to look like:</p>

<p><code class="language-plaintext highlighter-rouge">index.html</code>:</p>

```htmlmixed=
{% extends "tasks/layout.html" %}

{% block body %}
    <h1>Tasks:</h1>
    <ul>
        {% for task in tasks %}
            <li>{{ task }}</li>
        {% endfor %}
    </ul>
{% endblock %}

```

<p><code class="language-plaintext highlighter-rouge">add.html</code>:</p>

```htmlmixed=
{% extends "tasks/layout.html" %}

{% block body %}
    <h1>Add Task:</h1>
    <form action="">
        <input type="text", name="task">
        <input type="submit">
    </form>
{% endblock %}

```

<p>Notice how we can now get rid of much of the repeated code by <em>extending</em> our layout file. Now, our index page remains the same, and we now have an add page as well:</p>

<p><img src="https://cs50.harvard.edu/web/2020/notes/3/images/add.png" alt="Add"></p>

<p>Next, it’s not ideal to have to type “/add” in the URL any time we want to add a new task, so we’ll probably want to add some links between pages. Instead of hard-coding links though, we can now use the <code class="language-plaintext highlighter-rouge">name</code> variable we assigned to each path in <code class="language-plaintext highlighter-rouge">urls.py</code>, and create a link that looks like this:</p>

```htmlmixed=
<a href="{% url 'add' %}">Add a New Task</a>

```

<p>where ‘add’ is the name of that path. We can do a similar thing in our <code class="language-plaintext highlighter-rouge">add.html</code>:</p>

```htmlmixed=
<a href="{% url 'index' %}">View Tasks</a>

```

<p>This could potentially create a problem though, as we have a few routes named <code class="language-plaintext highlighter-rouge">index</code> throughout our different apps. We can solve this by going into each of our app’s <code class="language-plaintext highlighter-rouge">urls.py</code> file, and adding an <code class="language-plaintext highlighter-rouge">app_name</code> variable, so that the files now look something like this:</p>

```python=
from django.urls import path
from . import views

app_name = "tasks"
urlpatterns = [
    path("", views.index, name="index"),
    path("add", views.add, name="add")
]

```

<p>We can then change our links from simply <code class="language-plaintext highlighter-rouge">index</code> and <code class="language-plaintext highlighter-rouge">add</code> to <code class="language-plaintext highlighter-rouge">tasks:index</code> and <code class="language-plaintext highlighter-rouge">tasks:add</code></p>

```htmlmixed=
<a href="{% url 'tasks:index' %}">View Tasks</a>

<a href="{% url 'tasks:add' %}">Add a New Task</a>

```

<p>Now, let’s work on making sure the form actually does something when the user submits it. We can do this by adding an <code class="language-plaintext highlighter-rouge">action</code> to the form we have created in <code class="language-plaintext highlighter-rouge">add.html</code>:</p>

```htmlmixed=
<form action="{% url 'tasks:add' %}" method="post">

```

<p>This means that once the form is submitted, we will be routed back to the <code class="language-plaintext highlighter-rouge">add</code> URL. Here we’ve specified that we’ll be using a <em>post</em> method rather than a <em>get</em> method, which is typically what we’ll use any time a form could alter the state of that web page.</p>

<p>We need to add a bit more to this form now, because Django requires a token to prevent <a href="https://portswigger.net/web-security/csrf">Cross-Site Request Forgery (CSRF) Attack</a>. This is an attack where a malicious user attempts to send a request to your server from somewhere other than your site. This could be a really big problem for some websites. Say, for example, that a banking website has a form for one user to transfer money to another one. It would be catastrophic if someone could submit a transfer from outside of the bank’s website!</p>

<p>To solve this problem, when Django sends a response rendering a template, it also provides a <strong>CSRF token</strong> that is unique with each new session on the site. Then, when a request is submitted, Django checks to make sure the CSRF token associated with the request matches one that it has recently provided. Therefore, if a malicious user on another site attempted to submit a request, they would be blocked due to an invalid CSRF token. This CSRF validation is built into the <a href="https://docs.djangoproject.com/en/3.0/topics/http/middleware/">Django Middleware</a> framework, which can intervene in the request-response processing of a Django app. We won’t go into any more detail about Middleware in this course, but do look at the <a href="https://docs.djangoproject.com/en/3.0/topics/http/middleware/">documentation</a> if interested!</p>

<p>To incorporate this technology into our code, we must add a line to our form in <code class="language-plaintext highlighter-rouge">add.html</code>.</p>

```htmlmixed=
<form action="{% url 'tasks:add' %}" method="post">
    {% csrf_token %}
    <input type="text", name="task">
    <input type="submit">
</form>

```

<p>This line adds a hidden input field with the CSRF token provided by Django, such that when we reload the page, it looks as though nothing has changed. However, if we inspect element, we’ll notice that a new input field has been added:
<img src="https://cs50.harvard.edu/web/2020/notes/3/images/csrf.png" alt="CSRF"></p>

<a data-id="" id="django-forms" style="top: -58px;"></a><h3><a data-id="" href="#django-forms">Django Forms</a></h3>

<p>While we can create forms by writing raw HTML as we’ve just done, Django provides an even easier way to collect information from a user: <a href="https://docs.djangoproject.com/en/3.0/ref/forms/api/">Django Forms</a>. In order to use this method, we’ll add the following to the top of <code class="language-plaintext highlighter-rouge">views.py</code> to import the <code class="language-plaintext highlighter-rouge">forms</code> module:</p>

```python=
from django import forms

```

<p>Now, we can create a new form within <code class="language-plaintext highlighter-rouge">views.py</code> by creating a Python class called <code class="language-plaintext highlighter-rouge">NewTaskForm</code>:</p>

```python=
class NewTaskForm(forms.Form):
    task = forms.CharField(label="New Task")

```

<p>Now, let’s go through what’s going on in that class:</p>
<ul class="fa-ul">
  <li data-marker="*"><span class="fa-li"><i class="fas fa-square"></i></span>Inside the parentheses after <code class="language-plaintext highlighter-rouge">NewTaskForm</code>, we see that we have <code class="language-plaintext highlighter-rouge">forms.Form</code>. This is because our new form <a href="https://www.w3schools.com/python/python_inheritance.asp">inherits</a> from a class called <code class="language-plaintext highlighter-rouge">Form</code> that is included in the <code class="language-plaintext highlighter-rouge">forms</code> module. We’ve already seen how inheritance can be used in Django’s templating language and for styling using Sass. This is another example of how inheritance is used to take a more general description (the <code class="language-plaintext highlighter-rouge">forms.Form</code> class) and narrow it down to what we want (our new Form). Inheritance is a key part of Object Oriented Programming that we won’t discuss in detail during this course, but there are <a href="https://www.w3schools.com/python/python_inheritance.asp">many online resources</a> available to learn about the topic!</li>
  <li data-marker="*"><span class="fa-li"><i class="fas fa-square"></i></span>Inside this class, we can specify what information we would like to collect from the user, in this case the name of a task.</li>
  <li data-marker="*"><span class="fa-li"><i class="fas fa-square"></i></span>We specify that this should be a textual input by writing <code class="language-plaintext highlighter-rouge">forms.CharField</code>, but there are <a href="https://docs.djangoproject.com/en/3.0/ref/forms/fields/#built-in-field-classes">many other input fields</a> included in Django’s form module that we can choose from.</li>
  <li data-marker="*"><span class="fa-li"><i class="fas fa-square"></i></span>Within this <code class="language-plaintext highlighter-rouge">CharField</code>, we specify a <code class="language-plaintext highlighter-rouge">label</code>, which will appear to the user when they load the page. A <code class="language-plaintext highlighter-rouge">label</code> is just one of <a href="https://docs.djangoproject.com/en/3.0/ref/forms/fields/#core-field-arguments">many arguments</a> we can pass into a form field.</li>
</ul>

<p>Now that we’ve created a <code class="language-plaintext highlighter-rouge">NewTaskForm</code> class, we can include it in the context while rendering the <code class="language-plaintext highlighter-rouge">add</code> page:</p>

```python=
# Add a new task:
def add(request):
    return render(request, "tasks/add.html", {
        "form": NewTaskForm()
    })

```

<p>Now, within <code class="language-plaintext highlighter-rouge">add.html</code>, we can replace our input field with the form we just created:</p>

```htmlmixed=
{% extends "tasks/layout.html" %}

{% block body %}
    <h1>Add Task:</h1>
    <form action="{% url 'tasks:add' %}" method="post">
        {% csrf_token %}
        {{ form }}
        <input type="submit">
    </form>
    <a href="{% url 'tasks:index' %}">View Tasks</a>
{% endblock %}

```

<p>There are several advantages to using the <code class="language-plaintext highlighter-rouge">forms</code> module rather than manually writing an HTML form:</p>
<ul class="fa-ul">
  <li data-marker="*"><span class="fa-li"><i class="fas fa-square"></i></span>If we want to add new fields to the form, we can simply add them in <code class="language-plaintext highlighter-rouge">views.py</code> without typing additional HTML.</li>
  <li data-marker="*"><span class="fa-li"><i class="fas fa-square"></i></span>Django automatically performs <a href="https://developer.mozilla.org/en-US/docs/Learn/Forms/Form_validation">client-side validation</a>, or validation local to the user’s machine. meaning it will not allow a user to submit their form if it is incomplete.</li>
  <li data-marker="*"><span class="fa-li"><i class="fas fa-square"></i></span>Django provides simple <a href="https://developer.mozilla.org/en-US/docs/Learn/Forms/Form_validation">server-side validation</a>, or validation that occurs once form data has reached the server.</li>
  <li data-marker="*"><span class="fa-li"><i class="fas fa-square"></i></span>In the next lecture, we’ll begin using <strong>models</strong> to store information, and Django makes it very simple to create a form based on a model.</li>
</ul>

<p>Now that we have a form set up, let’s work on what happens when a user clicks the submit button. When a user navigates to the add page by clicking a link or typing in the URL, they submit a <code class="language-plaintext highlighter-rouge">GET</code> request to the server, which we’ve already handled in our <code class="language-plaintext highlighter-rouge">add</code> function. When a user submits a form though, they send a <code class="language-plaintext highlighter-rouge">POST</code> request to the server, which at the moment is not handled in the <code class="language-plaintext highlighter-rouge">add</code> function. We can handle a <code class="language-plaintext highlighter-rouge">POST</code> method by adding a condition based on the <code class="language-plaintext highlighter-rouge">request</code> argument our function takes in. The comments in the code below explain the purpose of each line:</p>

```python=
# Add a new task:
def add(request):

    # Check if method is POST
    if request.method == "POST":

        # Take in the data the user submitted and save it as form
        form = NewTaskForm(request.POST)

        # Check if form data is valid (server-side)
        if form.is_valid():

            # Isolate the task from the 'cleaned' version of form data
            task = form.cleaned_data["task"]

            # Add the new task to our list of tasks
            tasks.append(task)

            # Redirect user to list of tasks
            return HttpResponseRedirect(reverse("tasks:index"))

        else:

            # If the form is invalid, re-render the page with existing information.
            return render(request, "tasks/add.html", {
                "form": form
            })

    return render(request, "tasks/add.html", {
        "form": NewTaskForm()
    })

```

<p>A quick note: in order to redirect the user after a successful submission, we need a few more imports:</p>

```python=
from django.urls import reverse
from django.http import HttpResponseRedirect

```

<a data-id="" id="sessions" style="top: -58px;"></a><h2><a data-id="" href="#sessions">Sessions</a></h2>

<dl>
  <dt>At this point, we’ve successfully built an application that allows us to add tasks to a growing list. However, it may be a problem that we store these tasks as a global variable, as it means that all of the users who visit the page see the exact same list. In order to solve this problem we’re going to employ a tool known as <a href="https://docs.djangoproject.com/en/3.0/topics/http/sessions/">sessions.</a></dt>
  <dd>
    <p>Sessions are a way to store unique data on the server side for each new visit to a website.</p>
  </dd>
</dl>

<p>To use sessions in our application, we’ll first delete our global <code class="language-plaintext highlighter-rouge">tasks</code> variable, then alter our <code class="language-plaintext highlighter-rouge">index</code> function, and finally make sure that anywhere else we had used the variable <code class="language-plaintext highlighter-rouge">tasks</code>, we replace it with <code class="language-plaintext highlighter-rouge">request.session["tasks"]</code></p>

```python=
def index(request):

    # Check if there already exists a "tasks" key in our session

    if "tasks" not in request.session:

        # If not, create a new list
        request.session["tasks"] = []

    return render(request, "tasks/index.html", {
        "tasks": request.session["tasks"]
    })

# Add a new task:
def add(request):
    if request.method == "POST":

        # Take in the data the user submitted and save it as form
        form = NewTaskForm(request.POST)

        # Check if form data is valid (server-side)
        if form.is_valid():

            # Isolate the task from the 'cleaned' version of form data
            task = form.cleaned_data["task"]

            # Add the new task to our list of tasks
            request.session["tasks"] += [task]

            # Redirect user to list of tasks
            return HttpResponseRedirect(reverse("tasks:index"))
        else:

            # If the form is invalid, re-render the page with existing information.
            return render(request, "tasks/add.html", {
                "form": form
            })

    return render(request, "tasks/add.html", {
        "form": NewTaskForm()
    })

```

<p>Finally, before Django will be able to store this data, we must run <code class="language-plaintext highlighter-rouge">python manage.py migrate</code> in the terminal. Next week we’ll talk more about what a migration is, but for now just know that the above command allows us to store sessions.</p>

<p>That’s all for this lecture! Next time we’ll be working on using Django to store, access, and manipulate data.</p>

