Routing with Polymer and Flask

Posted by wmginsberg on feb 17th, 2017 | 10 minute read

This is the second guide on server-side routing with Polymer, with advice on how to attach a Flask server to Polymer Starter Kit. The first walks through getting (PSK) connected with Express.

As mentioned in the Routing with Polymer and Express article, Polymer only helps build the front end of your application. Your server-side technology is entirely up to you. From attending University hackathons as a sponsor, I’ve noticed many young developers are using Flask. Flask is a highly flexible and elegant Python server. Generally, it is used with a templating framework, Jinja2, but if you’d like to load data with a library like Redux or Uniflow, you can set up your project without one. This guide will walk through setting up a Polymer + Flask project without Jinja2.

Note: this is an overview, not a step-by-step codelab. However, you can follow along by checking out the corresponding ✨github repo✨.

---

I. What is Flask?

Flask is a self-described ~“micro web development framework for Python.”~ By “micro” framework, they mean that Flask is as lightweight and extensible as possible. Rather than making decisions for you about which database or auth service (etc) you ought to use, Flask remains bare and offers up a bunch of extensions that you can add piecemeal. Even though it’s simple and small, it is certainly production-grade and ready to scale with your app. A quick search shows that Twilio and Pinterest seem to be using it in production.

You can install Flask via pip - follow these instructions from the Flask site to get your machine up to date.

II. Setting up your server

There are only three quick steps to spin up a Flask server.

1. Create a new directory and create a new python file inside it. I’m naming my directory poly-flask/ and my file app.py. Add the code below into your app.py file.

// Import necessary library
from flask import Flask

// Instantiate a Flask app
app = Flask(__name__)

// Program the main route to send ‘Hello, World’
@app.route('/')
def hello_world():
 return 'Hello, World!'

2. Update the FLASK_APP variable in your terminal, so you run the right file. Remember to swap out “app.py” if you named your file differently. And, if you’re using Windows, you’ll want to swap out “export” for “set”.

$ export FLASK_APP=app.py

3. Start the server.

$ flask run

...and now it should be running locally! Visit http://127.0.0.1:5000/ to see your “Hello, World!” message. If you need to troubleshoot, or want to run an externally visible server, please refer to Flask’s Quickstart guide.

III. Bringing in the front end

For simplicity, I’ll be using Polymer Starter Kit in this article. Install the Polymer CLI, so you can run polymer init starter-kit within your directory, and a fresh PSK will appear within seconds.

Flask has default naming for your static and template files, which are cleverly titled static and templates. These can be changed, but I’m going to stick it for simplicity. Since we’re not using templates in this example, we won’t need a templates folder. Now, create a folder called static and move index.html, src/, and bower_components/ into it. This is the equivalent of your client folder in the Express scenario.

Since you’ve moved your bower_components/ folder, you’ll need to adjust your .bowerrc file. Adjust it (or create one if you don’t already have one), so Bower knows where to install new components.

{
 "directory": "static/bower_components"
}

For reference, this is what my poly-flask/ directory looks like now. Hidden files are not shown.

poly-flask/
├── README.md
├── app.py
├── app.pyc
├── bower.json
├── images/
├── manifest.json
├── package.json
├── polymer.json
├── static
│ ├── bower_components/
│ ├── index.html
│ └── src
│  ├── my-app.html
│  ├── my-icons.html
│  ├── my-view1.html
│  ├── my-view2.html
│  ├── my-view3.html
│  ├── my-view404.html
│  └── shared-styles.html

IV. Adding routes to the server

Adding routes to a Flask server is simple and declarative. Since we are building a single-page app with Polymer Starter Kit, where routes are all directed to index.html and App Toolbox elements process URL changes for us, our work here is just a few lines of code. We need to add the various routes and send our static index.html file rather than a plain string. Below is the new app.py file that can handle the PSK routes, setting up the server for our single page app.

// Import necessary libraries
from flask import Flask, current_app

// Instantiate a Flask app
app = Flask(__name__)

// Program various routes to send the static index.html file to the current app
@app.route('/')
@app.route('/view1')
@app.route('/view2')
@app.route('/view3')
def index():
 return current_app.send_static_file('index.html')

If you’d rather just have a catch-all implementation for any route, rather than adding them one by one like I did above, Flask makes this possible too.

// Import necessary libraries
from flask import Flask, current_app

// Instantiate a Flask app
app = Flask(__name__)

// Program catch-all for routes to send the static index.html file to the current app
@app.route('/', defaults={'path': ''})
@app.route('/<path:path>')
def index(path):
 return current_app.send_static_file('index.html')

IV. Why are you always sending `index.html`?

That’s because we are designing a single page app, where the client handles all of the routes. My <app-route> and <iron-pages> components are located in my top-level element, <my-app> which is housed in index.html.

That code intercepts any GET requests for routes (i.e.: “/view3”, “/view1”) that are sent to the server, processes them, and redirects the page to index.html to make the appropriate routing call. By handling all of this in the client, we’ve built a quicker app, saving an entire round trip server visit on each request! Check out the diagram below for an illustration of how a request from the client bounces to the server, is processed, returns to the client, and is routed to the corresponding view.

A page request's bold journey from client to server, to client again.


Now that you've set your server up to process all routes, try accessing your pages directly from the browser again. If it doesn’t work right away, make sure you’ve killed and restarted your node server in the command line, since you’ve edited server-side code. This will refresh the code that you’re running, and read your new routing rules properly.

Now, Polymer Starter Kit is served with Flask, with supported routing both client- and server-side! This routing pattern can handle direct requests for various URLs, super quick on-site navigation, and (if you have a service worker set up) offline page-to-page navigation. Feel free to send questions over on Twitter, or as issues on the repo!