Sunday, April 21, 2019

The Code Bits: Flask Project for Beginners: Inspirational Quotes

In this project, we will create a web application that displays a random inspirational quote.

The goal of this project is to learn about application factory and how to create templates in Flask.

This is the second part of the “Getting started with Flask series”. In the first part, we learned how to create a basic Hello World application using Flask and run it locally.

Installation and Setup

First, let us install the dependencies and setup our project directory. Basically what we need to do is:
  • Install Python. We will be using Python3 here.
  • Create a directory for our project, say “1_inspirational_quotes”, and go inside the directory.
    mkdir 1_inspirational_quotes
    cd 1_inspirational_quotes
  • We will create a virtual environment for our project where we will install Flask and any other dependencies. So go ahead and create a virtual environment and activate it.
    python3 -m venv venv
    . venv/bin/activate
  • Finally install Flask.
    pip3 install flask
    
If you need more instructions on installation, refer to Flask installation guide or Getting started with Flask.

Set up the Application Factory

Now that we have setup our project directory, the next thing that we need to do is to create the Flask application, which is nothing but an instance of the Flask class.

We could create the Flask instance globally, the way we did in Getting Started with Flask: Hello World. However, in this example, we will create it within a function.

Application Factory is the term used to refer to the method inside which we will create our application (Flask instance). All sorts of configuration and setup required for the application will also be done within the application factory. Finally it will return the Flask application instance.

So let us create a directory ‘quotes’ and add an __init__.py file to it. This will make the directory get treated as a Python package.

mkdir quotes
cd quotes
touch __init__.py

Then let us define our application factory in this file.

–> 1_inspirational_quotes/quotes/__init__.py

from flask import Flask

def create_app():
    """
    create_app is the application factory.
    """
    # Create the app.
    app = Flask(__name__)

    # Add a route.
    @app.route('/')
    def home():
        return 'Hello there! :)'

    # Return the app.
    return app

Notes:

  • The method create_app is the application factory.
  • Within the application factory, we created a Flask instance, app, which is nothing but our application. Note that __name__ refers to the package name here, i.e., quotes. This is what will be used as our application name.
  • Then we created a placeholder method, home, which will serve the content for our app page. For now, it just returns some string which will get displayed on our browser when we run the application.
  • The decorator, @app.route, links the URL (/) to the method, home.

Run the basic application

In order to make sure that everything is set up correctly, let us run the application and see if it is working.

First, let us set the FLASK_APP environment variable to be our application package name. This basically tells Flask which application to run.

export FLASK_APP=quotes

We will also set the environment variable FLASK_ENV to development so that:

  1. debug mode is turned on and the debugger is activated.
  2. the server will be restarted whenever we make a code change. We can make modifications to our code and simply refresh the browser to see the changes in effect.
export FLASK_ENV=development

Note: If you are on Windows, use set  instead of export.

Now we are ready to run the application. So go ahead and run it using the flask command. You should see an output similar to the following.

flask run
 * Serving Flask app "quotes" (lazy loading)
 * Environment: development
 * Debug mode: on
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 150-101-403

Note: Make sure that you are running the command from the ‘1_inspirational_quotes’ directory and not ‘quotes’. Otherwise, you will see the error “flask.cli.NoAppException: Could not import “quotes.quotes”.”

To see the app in action, go to http://127.0.0.1:5000/ on your browser. You should see our message displayed in it as shown in the following image.

Awesome! Now let us start building our quotes app.

Add a template

Currently, our app just displays the string, “Hello there! :)” to the user. In this section, we will learn how to create a template that shows a random inspirational quote.

Return HTML content from the application factory

The simplest way to achieve this is to return the HTML code as a string instead of our hello world string as shown below:

—> 1_inspirational_quotes/quotes/__init__.py

from flask import Flask

def create_app():
    """
    create_app is the application factory.
    """
    # Create the app.
    app = Flask(__name__)

    # Add a route.
    @app.route('/')
    def home():
        return '''
<html>
<body>
  I find that the harder I work, the more luck I seem to have. – Thomas Jefferson
</body>
</html>
'''

    # Return the app.
    return app

Now if you go to http://127.0.0.1:5000/, you should see the quote displayed on the screen:

Even though this works perfectly fine, this is not the best approach to serve HTML content for our application. First of all, the code does not look clean. Second, as our application grows, modifying and maintaining the template within the application factory will be tedious. So we need to isolate our template from the application factory.

Create a static HTML template file

A template is a file that contains static data as well as placeholders for dynamic data. In this section, we will just be creating static HTML template that displays a quote to our user. In a later section, we will see how to make it dynamic.

Within the quotes directory, let us add a directory to keep our templates and move our quotes template to a separate HTML file.

mkdir templates
touch templates/quotes.html

Note that our template is stored within a directory named templates under the application directory, quotes. This is where Flask expects its templates by default.

–>1_inspirational_quotes/quotes/templates/quotes.html

<!doctype html>
<html>
<body>
  I find that the harder I work, the more luck I seem to have. – Thomas Jefferson
<body>
</html>

Register the template with the application factory

Now we need to modify our application factory such that this HTML file is served when users visit our web page.

—> 1_inspirational_quotes/quotes/__init__.py

from flask import Flask, render_template

def create_app():
    """
    create_app is the application factory.
    """
    # Create the app.
    app = Flask(__name__)

    # Add a route.
    @app.route('/')
    def home():
        return render_template('quotes.html')

    # Return the app.
    return app

Note how we introduced the method, render_template(). In this case, it takes our HTML file name and returns its contents. Later on, when we learn about serving dynamic content, we will learn more about rendering and how Flask uses Jinja for template rendering.

Now if we go to http://127.0.0.1:5000/, we should see the quote displayed on the screen just as we saw earlier.

Update the template to render quotes dynamically using Jinja

Now that we have learned how to create a template and register it with the application factory, let us see how we can serve content dynamically.

Right now our app just displays the same quote every time someone visits. Our goal is to dynamically update the quote by selecting one randomly from a set of quotes.

First, let us go ahead and create a list of quotes. To keep things simple, we will be adding it in memory within the application factory. In a later post, we will explore how to use databases with Flask.

—> 1_inspirational_quotes/quotes/__init__.py

from flask import Flask, render_template
import random

def create_app():
    """
    create_app is the application factory.
    """
    # Create the app.
    app = Flask(__name__)

    # Add a route.
    @app.route('/')
    def home():
        sample_quotes = [
            "I find that the harder I work, the more luck I seem to have. – Thomas Jefferson",
            "Success is the sum of small efforts, repeated day in and day out. – Robert Collier",
            "There are no shortcuts to any place worth going. – Beverly Sills",
            "The only place where success comes before work is in the dictionary. – Vidal Sassoon",
            "You don’t drown by falling in the water; you drown by staying there. – Ed Cole"
        ]

        # Select a random quote.
        selected_quote = random.choice(sample_quotes)

        # Pass the selected quote to the template.
        return render_template('quotes.html', quote=selected_quote)

    # Return the app.
    return app

As you can see, now we are passing an additional parameter, quote, to the render_template function. Flask uses Jinja to render dynamic content in the template. With this change, the variable, quote, becomes available in the template, quotes.html. Now let us see how we can update the template file to make use of this variable.

–>1_inspirational_quotes/quotes/templates/quotes.html

<!doctype html>
<html>
<body>
  
<body>
</html>

Here, is the delimiter used by Jinja to denote expressions which will be evaluated and rendered in the final HTML document.

Now if we go to http://127.0.0.1:5000/ and keep refreshing the page, we should see a different random quote selected from the list every time. A demo is shown below:

Add a stylesheet

As of now, our app works, but it looks very plain. So now we will see how to add a simple stylesheet to it.

In Flask, just like templates were expected to be in the templates directory by default, static files like CSS stylesheets are expected to be in static directory within the application folder.

So go ahead and create the directory and add a CSS file style.css to it.

mkdir static
touch static/style.css

—>1_inspirational_quotes/quotes/static/style.css

body {
  background-color: black;
  background-image: url("background.jpg");
  background-size:cover;
}
.quote_div {
  text-align: center;
  color: white;
  font-size: 30px;
  padding: 25px 5px;
  margin: 15% auto auto;
}

You can also add a background image and keep it under the static directory as shown above.

Now let us modify the template to use the stylesheet.

–>1_inspirational_quotes/quotes/templates/quotes.html

<!doctype html>
<html>
<head>
  <link rel="stylesheet" href="">
</head>
<body>
  <div class="quote_div">
    
  </div>
<body>
</html>

Now if we go to http://127.0.0.1:5000/, we will see a nicer app! A demo:

Conclusion

In case you want to browse through the code or download and try it out, the Github link for this project is here.

In this post, we learned how to create a basic Flask application that serves dynamic data using a Jinja template.

For more advanced lessons with projects, stay tuned and subscribe to our blog!



from Planet Python
via read more

No comments:

Post a Comment

TestDriven.io: Working with Static and Media Files in Django

This article looks at how to work with static and media files in a Django project, locally and in production. from Planet Python via read...