Making a Banner Generator With Pillow and Flask

Bob, Sat 19 August 2017, Tools

challenges, Flask, Flask-SQLAlchemy, Flask-WTF, Heroku, images, Pillow, PyBites Banner Generator

In this article I will take last week's Pillow script and integrate it into a Flask app.

I ended up creating our PyBites Banner Generator. Want to try it? The app is on Heroku. Want to fork it? For example to use it with your own brand logos? The code is on Github.

How it works

Give your banner a name, a background URL and text. We use PyBites logos upon login. Logged out state has a Python logo but I probably make this a free field so you can input any URL. Leaving "Use Second Image as Background" unchecked aligns the second image to the right:

home logged out

This results in:

logged out banner

Upon login it also caches the form input parameters to easily recreate the banners:

home logged in

Logged it uses PyBites logos. Here is the same banner logged in:

banner with pybites article logo

And the banner's form data can be retrieved again by clicking its name in the right "Cached Banners" list.

Let's make a Twitter digest banner. Ticking "Use Second Image as Background" turns it into background image:

another banner with background


banner of pybites twitter digest

What's under the hood?

Here are the pieces that make up this app:


Last week's article detailed the Pillow script which is in the banner package. The generate_banner takes a img_banner named tuple, instantiates a Banner object, and creates and saves the image.

Since last time I added a add_background method which you saw in the 3rd example above. I also made add_text smarter about aligning text: if background is ticked it uses the extra free space to the right and if the text is less than 2 lines long (using Python's textwrap), it adds more top padding to it.


Flask-WTF integrates Flask and WTForms making working with forms a joy.

In I subclass wtforms's Form class, read in the logos for the dropdown and add some validations using wtform's validators.

The form is diplayed in imageform.html and _formhelpers.html in the templates dir which I copied from this wtforms pattern.


We have covered Flask-SQLAlchemy before. I use it here to store the image parameters in a DB when logged in. Why not the images? Heroku has an ephemeral filesystem so they would be lost after a dyno restart (which happens often because I am using the hobby version now). For this same reason Heroku provides production grade PostgreSQL databases as a service.

The SQLAlchemy model code is in including code under main to recreate the DB. Obviously I need to look at a tool like Alembic to properly handle future DB migrations.


The core logic is in It started simple with 57 lOC, growing to 139 LOC as of this writing. Not bad considering that it does form handling, image generation, caching and handling a simple login session.

Some interesting things:


Code Challenge

This project was part of Code Challenge 31 - Image Manipulation With Pillow - if you want to play with Pillow and potentially Flask and Heroku, follow the instructions there and start coding and PR your code to our challenges repo. I hope this article inspired you to give it a try yourself.

Flask vs Django

Yeah I know what you are thinking: "But it's 100 days of Django, why not a Django app?" Glad you asked. For this case I think Flask was the right choice. Julian shared some more thoughts about when to use one or the other, you can check it out here.

Further reading

Keep Calm and Code in Python!

-- Bob

PyBites Python Tips

Do you want to get 250+ concise and applicable Python tips in an ebook that will cost you less than 10 bucks (future updates included), check it out here.

Get our Python Tips Book

"The discussions are succinct yet thorough enough to give you a solid grasp of the particular problem. I just wish I would have had this book when I started learning Python." - Daniel H

"Bob and Julian are the masters at aggregating these small snippets of code that can really make certain aspects of coding easier." - Jesse B

"This is now my favourite first Python go-to reference." - Anthony L

"Do you ever go on one of those cooking websites for a recipe and have to scroll for what feels like an eternity to get to the ingredients and the 4 steps the recipe actually takes? This is the opposite of that." - Sergio S

Get the book