You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
319 lines
7.2 KiB
319 lines
7.2 KiB
<!--
|
|
title: Next Steps in Web Development
|
|
type: lesson
|
|
duration: "01:00"
|
|
creator: Kevin Coyle
|
|
-->
|
|
|
|
##  {.separator}
|
|
|
|
<h1>Templates</h1>
|
|
|
|
---
|
|
|
|
## Learning Objectives
|
|
*After this lesson, you will be able to:*
|
|
|
|
- Create a template HTML document.
|
|
- Pass variables to a template HTML document via a Flask app.
|
|
|
|
---
|
|
|
|
## A Million Copies
|
|
|
|
- Don't you hate it when you have to repeat yourself?
|
|
|
|
- What if you had a website with 10 pages that were almost the same?
|
|
|
|
- Would you code them all from scratch?
|
|
|
|
---
|
|
|
|
## We Do: Your `index.html` Page
|
|
|
|
- Any route can use an `html` page.
|
|
|
|
- Try it!
|
|
- In your `my_website.py`, set the `/randnum/<inte>` and `/` routes to both `render_template("index.html")`.
|
|
|
|
- What if we want them to display a different heading?
|
|
- Do we need to rewrite the whole file?
|
|
|
|
---
|
|
|
|
## No! That's What Templates Are For!
|
|
|
|
<aside class="notes">
|
|
|
|
**Teaching Tip:**
|
|
|
|
- Talk for a few minutes here about design patterns and why it's important to split data from presentation.
|
|
</aside>
|
|
|
|
We use templates to:
|
|
|
|
- Write one HTML file.
|
|
- Pass it variables.
|
|
- Transfer info from Flask to HTML.
|
|
|
|
As well as for one important design reason:
|
|
|
|
- We can separate data from how we present data to users.
|
|
|
|
---
|
|
|
|
## Jinja2
|
|
|
|
- One of the most widely used template engines for Python.
|
|
- Used in places that you might have visited already, like Instagram or NPR.
|
|
|
|
---
|
|
|
|
## Why Jinja2?
|
|
|
|
<aside class="notes">
|
|
|
|
**Talking Points:**
|
|
|
|
- Jinja2 is kind of like the engine that powers our vehicle (Flask). However, this happens behind the scenes.
|
|
- We're quickly peering behind the scenes to get an idea of what our engine can do.
|
|
|
|
- Some examples of what makes Jinja2 awesome are:
|
|
- **Template inheritance:** You can extend templates in very efficient ways.
|
|
- **HTML escaping:** Malicious hackers can create XSS attacks by injecting HTML code into our site where other users insert data. Jinja2 helps us avoid that.
|
|
- **Speed and efficiency:** Jinja2 is very fast. It compiles optimized Python code.
|
|
- **Flexibility and extensibility:** It's really easy to add our own filters and functions.
|
|
</aside>
|
|
|
|
Jinja2 has some really powerful features that web design folks want to take advantage of:
|
|
|
|
- Template inheritance
|
|
- Like class inheritance!
|
|
- HTML escaping
|
|
- Stops some hacking attacks (XSS and SQL injection).
|
|
- Speed and efficiency
|
|
- Optimized Python code.
|
|
- Flexibility and extensibility
|
|
- We can add our own filters and functions.
|
|
|
|
|
|
---
|
|
## Knowledge Check: Discussion
|
|
|
|
- What's one reason why we might want to use templates, other than staying DRY?
|
|
|
|
<aside class="notes">
|
|
|
|
**Talking Point:**
|
|
|
|
- Answer: Templates allow us to add programming languages to our HTML templates.
|
|
</aside>
|
|
|
|
- What's template inheritance?
|
|
|
|
<aside class="notes">
|
|
|
|
**Talking Point**:
|
|
|
|
- Template inheritance is extending templates in very efficient ways.
|
|
</aside>
|
|
|
|
|
|
---
|
|
|
|
## Expanding on Our `index.html`
|
|
|
|
- We'll send a `greeting` variable into our `index.html` from both routes.
|
|
|
|
- The routes will display different things!
|
|
|
|
---
|
|
|
|
## Adding Templates
|
|
|
|
<aside class="notes">
|
|
|
|
**Talking Points:**
|
|
|
|
- This is the function that Flask uses to… you guessed it: Render our template(s)!
|
|
- For this exercise, we want to add some programming language (Python) into our HTML template.
|
|
</aside>
|
|
|
|
- Remember `import render_template`?
|
|
- This is the function that Flask uses to… you guessed it: Render our template(s)!
|
|
|
|
---
|
|
|
|
## Edit `index.html`
|
|
|
|
- Change the `<h1>` to be `{{ greeting }}`.
|
|
|
|
```html
|
|
...
|
|
<body>
|
|
<h1>Hello {{ name }}!</h1>
|
|
<p>If music be the food of love, play on!</p>
|
|
....
|
|
```
|
|
|
|
---
|
|
|
|
## Templating Syntax With Jinja
|
|
|
|
<aside class="notes">
|
|
|
|
**Talking Points:**
|
|
|
|
- What's awesome about this is that inside of these brackets, we can pass in Python syntax.
|
|
- In our example, we have a variable, which we're calling `name`.
|
|
- Whatever we assign to the variable `name` will be rendered when our page renders.
|
|
- Statements are where we would pass in logic like {%if this thing%} {% else that thing%}.
|
|
</aside>
|
|
|
|
- Recognize the `{{}}`?
|
|
|
|
- In Jinja, **templates** are rendered with double curly brackets (`{{ }}`).
|
|
|
|
- **Statements** are rendered with curly brackets and percent signs (`{% %}`).
|
|
|
|
- A use case here is passing in logic like:
|
|
```python
|
|
{% if name == 'kevin' %}
|
|
# Do the thing
|
|
{% else %}
|
|
# Do all the other things.
|
|
```
|
|
|
|
---
|
|
|
|
## Rendering a Template in Flask
|
|
|
|
<aside class="notes">
|
|
|
|
**Talking Points:**
|
|
|
|
- We're going to modify the rest of our Flask app to pass some values into our variable in the template (curly braces).
|
|
- Let's change the rest of our `hello_flask.py` so that the whole thing looks the following script on screen.
|
|
|
|
- Here, we use `render_template` function which takes in two arguments:
|
|
1. Our template name, `index.html`.
|
|
1. Our **context** which, from the documentation is "the variables that should be available in the context of the template."
|
|
|
|
- Here, our variable is name which is passed into the <user> part of our route, and then becomes the value that we assign to the variable called `name`.
|
|
</aside>
|
|
|
|
Let's change our `my_website.py` accordingly:
|
|
|
|
```python
|
|
@app.route('/')
|
|
def home():
|
|
return render_template("index.html", greeting="Hello World!")
|
|
|
|
...
|
|
|
|
@app.route('/shownum/<inte>')
|
|
def shownum(inte):
|
|
my_greeting = "Your number is " + str(inte)
|
|
return render_template("index.html", greeting=my_greeting)
|
|
```
|
|
|
|
---
|
|
|
|
## Try it!
|
|
|
|
- Check out: `http://localhost:5000`.
|
|
- Then: `http://localhost:5000/shownum/26`.
|
|
|
|
Do your other routes still work?
|
|
|
|
---
|
|
|
|
## Knowledge Check: Discussion
|
|
|
|
What two arguments did we pass into the `render_template` function?
|
|
|
|
<aside class="notes">
|
|
|
|
**Talking Point:**
|
|
|
|
- Answer: `index.html`, our template name, and `greeting`, which is our context.
|
|
</aside>
|
|
|
|
What's one reason we use templates?
|
|
|
|
<aside class="notes">
|
|
|
|
**Talking Points:**
|
|
|
|
Possible answers:
|
|
- Adding programming languages to our HTML templates.
|
|
- Transferring info from Flask to HTML.
|
|
- Lets us separate data from how we present data to users.
|
|
</aside>
|
|
|
|
---
|
|
|
|
## Your Turn!
|
|
|
|
- Create a new Flask app, `shakespeare.py`.
|
|
- Create a new template HTML file, `hello.html`.
|
|
- It will display a paragraph with a parameter `poem` in it.
|
|
- Render it from the index endpoint.
|
|
- Remember calling in variables from the last lesson?
|
|
- Have your Flask app read in the poem saved in `hi.txt`, then pass that to the `hello.html` template to display.
|
|
- Launch your Flask app and check the results!
|
|
|
|
---
|
|
|
|
## Template Solution
|
|
|
|
```html
|
|
<!doctype html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<title>Shakespeare</title>
|
|
</head>
|
|
<body>
|
|
<p>{{text}}</p>
|
|
</body>
|
|
</html>
|
|
```
|
|
|
|
---
|
|
|
|
|
|
## Python Solution
|
|
|
|
```python
|
|
from flask import Flask, render_template
|
|
import os # Note the new import — to be in the file system.
|
|
|
|
app = Flask(__name__)
|
|
|
|
file_path = '.'
|
|
|
|
with open(os.path.join(file_path, 'hi.txt')) as f:
|
|
the_text = f.read()
|
|
|
|
@app.route('/') # When someone goes here...
|
|
def home(): # Do this.
|
|
return render_template("hello.html", text=the_text)
|
|
|
|
if __name__ == '__main__':
|
|
app.run(debug=True)
|
|
```
|
|
|
|
|
|
|
|
---
|
|
|
|
## Summary
|
|
|
|
- Jinja:
|
|
- A popular templating engine.
|
|
- Templates save us time and abstract presentation from data.
|
|
|
|
- Template fun:
|
|
- We can pass variables into the template from the Flask app and the URL.
|