Download Kite Free! Install Kite Free!

A Guide to Python’s Flask Web Interface

Eric J. Ma
February 5, 2019

In the first two parts of this blog series, I first showed you how to create WiFi access QR codes programmatically with Python and 3D print them, and then how to design and build a command-line interface (CLI) program that will let you make QR codes by typing a few prompts at the terminal.

In this blog post, I’d like to demonstrate how to build a web app that creates QR codes using WiFi information that an end-user can input. Having built this app, you will hopefully come to the same conclusion as I did: command line apps and web apps are just text-based endpoints to arbitrary Python code. Once you’ve realized this, the process of making both web and command-line apps will hopefully be much less mystical!

What is Flask?

Many people who use our QR codes do not want to generate them from the command line. Browser-based interfaces let us know that all our users will have roughly the same experience, regardless of the way their system is set up. Perhaps more importantly, we can worry less about the tedious parsing of command line arguments. A consistent front-end lets the developer focus on application logic instead of infrastructure.

Flask is a bare-bones Python framework for building apps that use the web browser as the front-end, rather than the command-line as the front-end. Flask abstracts away lower-level tasks, such as setting up a development web server, managing information flow from the browser to the Python interpreter, and more. Using Flask thus allows you, the developer, to focus on the application logic rather than worrying about infrastructural things.

Flask is a bare-bones framework for attaching your code to to user actions in a browser, via simple callback functions. Flask is often called a “micro-framework” to distinguish it from feature-rich, higher overhead options like Django. For more details, I’d encourage you to check out the Flask website; aside from that, though, nothing beats building an app to learn how to use a framework, so hopefully this app we are going to build will also augment your intuition about Flask!

Structuring a Flask app

In order to build a Flask app, you’ll need the following minimal directory structure:

project
├── templates
└── app.py

We write our Flask app into app.py. In the templates/ directory, we store the HTML templates that our Flask app will use to display to the end user. In our previous blog post, we had the following structure:

├── environment.yml
├── qrwifi
│├── __init__.py
│├── app.py
│├── cli.py
│├── functions.py
│└── templates
│├── index.html.j2
│├── qr.html.j2
│└── template.html.j2
└── setup.py

In our previous blog post, we had the following structure:

Building the Flask app

Let’s start with app.py. As with the previous post, I’ll build your intuition bit-by-bit, and then I’ll put together a final copy/pastable segment of code that you can easily run. You can follow along with the full code from this project on Kite’s github repository.

├── environment.yml
├── qrwifi
│├── __init__.py
│├── app.py **
│├── cli.py
│├── functions.py
│└── templates
│├── index.html.j2
│├── qr.html.j2
│└── template.html.j2
└── setup.py

from flask import Flask, render_template, request

from qrwifi.functions import wifi_qr


app = Flask(__name__)

The first line of imports contains the most commonly-used set of Flask objects and functions that we will be using. The second line of imports lets us import the wifi_qr function from our qrwifi.functions module, which itself is installable. Finally, the third line lets us create a Flask object, to which we assign it the variable name app.

Once this basic infrastructure is in place, we can get to work defining what Flask considers “view functions”.

Working with view functions

The best way to think about view functions is as functions that are called when you type a URL into your browser. The location you type is the URI, sometimes called an endpoint, and the function itself referred to as a callback–a function called in response to some event. Our callback returns a template, which we’ll call a “view” when working with Flask. Let’s see an example:

@app.route("/")
def home():
return render_template("index.html.j2")

Here, we’ve defined the home() function, which is called when we enter the routing string after our hostname in the URL bar of our browser. There’s a lot to unpack there, so let’s break it down.

Routing string?

If you go to your browser and type the following URL:

http://kite.com/blog

You’ll be brought to the Kite blog. kite.com is the string that points us to the server that is hosting the blog, and /blog is the routing string that tells us where to go. Together, they form the URI, a “uniform resource indicator”.

Just remember, a URL is where the server lives, like a top-level directory, and a URI is and endpoint where a specific resource lives.

With Flask apps, we only have to specify the routing string and the appropriate function that gets called when the routing string is entered into the user’s browser. In this case, /, which canonically routes to the homepage of the website, is assigned to call on the home() function, which returns a function call to render_template.

What render_template does here is tells the Flask app to fill in whatever is needed in the template, and then return the resulting HTML page to the browser.

home() is not particularly interesting, since all we’re doing is rendering an HTML template that has no variable regions. Let’s take a look at that template — the asterisks (**) indicate the file we are currently editing.

HTML Template

├── environment.yml
├── qrwifi
│├── __init__.py
│├── app.py
│├── cli.py
│├── functions.py
│└── templates
│├── index.html.j2 **
│├── qr.html.j2
│└── template.html.j2
└── setup.py

{% extends "template.html.j2" %}


{% block body %}

<div class="row">
  <div class="col-12">
    <h1>WiFi QR Code Creator</h1>
  </div>
  <div class="col-12">
    <form action="/create" method="post">
      <div class="form-group">
        <label for="ssid">SSID</label>
        <input class="form-control" type="text" name="ssid" id="ssid" placeholder="My WiFi Network Name">
      </div>

      <div class="form-group">
        <label for="security">Security Mode</label>
        <select class="form-control" name="security" id="security">
          <option value="WPA">WPA</option>
          <option value="WEP">WEP</option>
          <option value="">None</option>
        </select>
      </div>

      <div class="form-group">
        <label for="password">Password</label>
        <input class="form-control" type="password" name="password" id="password" placeholder="Protection is good!">
      </div>

      <div class="form-group">
        <button class="btn btn-lg btn-success" type="submit">Create QR Code!</button>
      </div>

    </form>
  </div>
</div>

{% endblock %}

“index.html.j2”

I won’t go into too much depth about the HTML here, since HTML is not the main focus of the blog post. However, it’s important to recognize that an HTML page with a form on it allows users to input their SSID, security type, and password. Of course, knowing HTML is a prerequisite for building useful things on the web.

Be sure to check out the github repository referenced earlier for the complete flask application.

The other useful thing to mention for you to learn is the jinja2 syntax. Jinja2, usually just called “Jinja” in conversation, is a special templating language, a version of HTML that we can use to organize our HTML code. While you don’t need to be an expert in Jinja2 to benefit from Flask, it’s important to see what a templates are, and how they fit into a Flask application.

View functions (cont.)

Let’s go back to the view functions in app.py. From the homepage, we have created an HTML form that an end-user can input their WiFi information into. We now need a view function that will show the resulting QR code. Let’s call it create(), which points to the routing string /create.

@app.route("/create", methods=["POST"])
def create():
res = request.form
qr = wifi_qr(ssid=res["ssid"], password=res["password"], security=res["security"])
qr_b64 = qr.png_data_uri(scale=10)
return render_template("qr.html.j2", qr_b64=qr_b64)

In the create() function, we do a few things.

First, we obtain the submitted data from the form which we can use as a dictionary that we can key into. We then pass that information into the wifi_qr function which we imported from functions.py. Finally, we create the base64-encoded version of the QR code, which will let us display the QR code in the qr.html.j2 template.

QR Code Display Template

Let’s take a look at that particular template. (qr.html.j2)

{% extends "template.html.j2" %}

{% block body %}
<div class="row">
    <div class="col-12">
        <h1>WiFi QR Code Creator</h1>
        <p>Here is your QR Code!</p>
        <img src="{{ qr_b64|safe }}">
    </div>
</div>
{% endblock %}

In this section, the importance of the templating engine comes to light. We can insert the base64-encoded PNG version of the QR code into the HTML page by passing the qr_b64 variable into the render_template()function, which then gets inserted inside the <img> tag. The base64-encoded QR code is going to vary, but the HTML tags surrounding it stay the same, so we only have to set it as a variable in the HTML template.

Back to the View Function

Finally, let’s introduce the last part of app.py.

def run():
app.run(debug=True, port=5690, host="0.0.0.0")

if __name__ == "__main__":
run()

What we’ve basically done here is serve the Flask app on port 5690 on our localhost. I chose to use a wrapper similar to the CLI app so that we can also launch the Flask app from the command-line. Pythonistas consider it a best practice to always keep some command-line functionality.

Putting it all together

With that, let’s see the entirety of app.py together:

from flask import Flask, render_template, request

from qrwifi.functions import wifi_qr


app = Flask(__name__)


@app.route("/")
def home():
return render_template("index.html.j2")


@app.route("/create", methods=["POST"])
def create():
res = request.form
print(res)
qr = wifi_qr(ssid=res["ssid"], password=res["password"], security=res["security"])
qr_b64 = qr.png_data_uri(scale=10)
return render_template("qr.html.j2", qr_b64=qr_b64)


def run():
app.run(debug=True, port=5690, host="0.0.0.0")

if __name__ == "__main__":
run()

Using the QR Code Creator

As an additional step, if you type at the terminal:

$ python app.py

you can then go to your browser, and input localhost:5690, and your Flask app will be live.

Concluding Thoughts

I hope you’ve found this blog series helpful! Along the way, you’ve learned how to create QR codes using Python, how to create a QR code from the command-line, and finally, how to build a web front-end to the same QR code creation code.

At the end of the day, if there’s a key takeaway, I hope you’ve come to realize it’s that CLIs and web apps are nothing more than text-based front-ends to arbitrary code in the backend. Having this idea in the back of my mind has been extremely helpful for me while learning about web and CLI app development.

Building apps like these, particularly Flask apps, sharpens my intuition about the web each time I embark on a project. If you’d like to read the code in more detail, you can go to Kite’s companion github repository for this post. More than that, however, I hope you will go forth and build something useful using the ideas that you’ve learned from these blog posts!