Jonnie Grieve Digital Media: Blog

Home
by on 27th August, 2021 - 2:53pm (0)

Blog: Integrating SQLAlchemy with Flask – #2 (More Posts)

In a new series of blogs related to SQLAlchemy, I’m moving away from the command line environment and moving on to exploring how Python, Flask, and SQLAlchemy can work together to make a website driven by external data.

Recap

When I left it in my last blog, there was only one route with no data and an app file displaying one page on a local server. By the end of this blog, the project will be expanded to include at least 3 routes, each defined by its own Python function. It will include a page with a form for adding new details to a table of data which will eventually be made from an SQLAlchemy database. It will demonstrate how to include templates and static files that link stylesheets and script files difference to a Flask website.  It will set up a local server that can be used to load files via localhost which can be visited via a local URL like this one (http://127.0.0.1:8000/) You can access it directly in your console/terminal using python/python3 app.py.

We already know now how to render some HTML using a template. And we’ve seen how Flask needs to know what to display. And that’s why we used a Python Decorator and function, like this.

# import flask and related modules
from flask import Flask, render_template

# define a new instance of a Flask Applicationm
app = Flask(__name__)


@app.route('/')
def index():
    return "A message displayed to the home route in your browser"

You may have noticed the render template module at the top.  I’ll use that in a moment, but for now, all the function is doing is returning a message to the applications’ home route via a simple function. Opening the above URL now would display that text on a white screen.

But now it’s time to start making a web page, a website.

I mentioned in my last blog that you can store HTML templates for your app in a directory called templates.  This is the directory Flask looks at to find these templates, so each project should have one.  Without it, it will not be found and generate a TemplateNotFound error.

If you haven’t already, create a directory at the root of your project called “templates”.

mkdir templates

Now you can start building templates.  Let’s start by making an index.html file inside the templates directory.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">


<title>Flask with SQL</title>

<link rel="stylesheet" type="text/css" href="static/style.css">
</head>
<body>
  <h1>Flask with SQL></h1>

  <p>Index.html content</p>
<body>
</html>

This will render some HTML to the screen.  But there’s already a potential issue to resolve. To demonstrate let’s make a new directory and some files for the project with

mkdir static
cd static
touch style.css
touch app.js

Just as the templates directory is a directory for application templates to go into we also have a place for static assets to go into.  In the template file above I’ve tried to link to the application stylesheet in the usual way. “href=”static/style.css”. That does work, but there’s a better way.  This is a Flask application, so we can use the url_for() method to link to applications assets such as stylesheets

{{url_for('static', filename='style.css')}}

This allows Flask to generate its own URL endpoints so we’re in safer hands than hard coding our own paths.  Here we simply pass in the directory to look into and the filename as arguments.  I also like to use SASS files inside the “static” directory so I have even more control over the styles I use in my project. With Ruby SASS I can watch for changes in sass partial files which output to a .css file which is in turn picked by Flask all inside the same directory.  If you have arguments which you want to pass in at runtime you can also do this in the url_for() method.

Handling HTML Templates in Flask

Now it’s time to introduce the concept of separation of concerns where we have an HTML file which we can use to “extend” its content into other more unique templates.

In your project, create 3 more new templates

cd ../ 
cd templates
touch main.html
touch one.html
touch two.html
touch four.html

Let’s look at main.html first

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">


<title>{% block title_block %} {% endblock %}</title>

<link rel="stylesheet" type="text/css" href="{{url_for('static', filename='style.css')}}">
</head>
<body>

<header>

<h1>Flask with SQL</h1>

{% block nav_block %} {% endblock %}

</header>

<main>

{% block main_block %}

{% endblock %}

{% block btn_block %} {% endblock %}


</main>

<footer>
<p>Flask with SQL by JGDM</p>
</footer>


<script type="text/javascript" src="{{url_for('static', filename='app.js')}}"></script>

</body>
</html>

There’s a lot of changes, I’ve made here. I’ve started my moving a lot of the markup from index.html through to main.  This will be the main layout file for this website.

In order to separate the main layout content and the unique content we use content blocks in the areas of the layout where you want the unique content to be.  For example, you might want to put a content block for your main navigation inside a <nav> element which would be a child of a <header> element. And then you would place that content inside a corresponding content block that lives inside another template file.

To show you what I mean, I’ll use the three.html template.

{% extends "main.html" %}

    {% block title_block %} title index 3 {% endblock %}

        <h1>Flask with SQL</h1>
        {% block nav_block %}
        <nav>
            <ul>
                <li><a href="/" class="selected" >One</a></li>
                <li><a href="/two">Two</a></li>
                <li><a href="/three">Three</a></li>
            </ul>
        </nav>
        {% endblock %}
 
        {% block main_block %}
            <h2>Three</h2>
            
            <p>Lorem 3</p>
        {% endblock %}

First, at the top of the file, you use the {% extends %}  keyword to copy across the markup from the main content file so it’s available to the individual template.

Now to create unique page content with content blocks.  The syntax is as follows:

{% block name_of_block%}  <p>Add your markup here</p> {%endblock %}

What’s the difference between the way 2 content blocks of the same name are used?

Add empty content blocks to define the position of the block in your markup and then add the unique content in the individual rendered template.  So to clarify, one main layout template defines where the unique content goes in your design, and the rest of the templates have content blocks to display the content.

Let’s go back to the app.py file one more time.

from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def index():
    return render_template("index.html")
    
@app.route('/two')
def two():
    return render_template("two.html")
    

@app.route('/three')
def three():
    return render_template("three.html")

@app.route('/form', methods=["GET", "POST"])
def main_form():
    return render_template("form.html")
    

if __name__ == '__main__':
    app.run(debug=True, port=8000, host='127.0.0.1')

Here we have  render_template on the import list. This is included so that we can use our HTML templates with the render_template() method.  And finally, we define one function for each route in our app, that returns a string value of the filename of the template.

So let’s recap what we have right now to close out the blog.

  • There are 4 HTML template files in the app, each located in the templates/ directory of the project.
  • 1 is the main.html – which is the website layout template. This has the main markup, empty content blocks to define the location of the apps unique content
  • There are 4 other  HTML template files that contain all the unique content in the app.  They index.html, form.html, two.html, and three.html
  • We are able to do this using Flasks’ “content blocks” ({% %} that are embedded into the templates.
  • There is also a directory called static which contains the main assets like sass partials, main style sheet, and script file, which is linked to the project using Flask url_for() method.

Now we have gone from a simple Flask app with 1 render template to a small site with, styles, a script, and a series of unique content templates.

This post has been assigned to the following categories

    Leave a Reply

    Your email address will not be published. Required fields are marked *