Hi everyone.

Today, I want to finally solve my issue with serving static files with Flask framework.

Static files in Django / Flask world are all files hosted on your server, that does not contain any python code.

Which are basically all non .py files, likes CSS, JS, images etc.

I don’t know why is Jinja2 template system built this way, but linking images or other static files in your HTML template won’t make them magically appear in your browser.

Your browser will complain, that files cannot be found.

With Apache stack (PHP, HTML), you would just point to your static files path, like www.domain.com/images/image.png.

Url is then translated into absolute path on your server, like /www/images/image.png.

But with Nginx and Gunicorn, nothing works out of the box.

I have to make some configurations before I can display my static files.

Let’s do itย  now.

Look at the Nginx configuration if the path to static files is properly configured.


It seems the path is wrong.

location /static {
    root /path/fiancia/static/; # <- let nginx serves the static contents

I will change it to…

location /static {
    root /path/financia/; # <- let nginx serves the static contents

Otherwise I would have to store my static files at path/financia/static/static/images/image.png.

This was the most frustrating thing I faced as a beginner.

I didn’t know that Nginx adds additional /static/ to your path.

Lost few days of trials and errors before I figured out.

Ok, now I restart Nginx so the changes in configuration are applied.

sudo brew services restart nginx

If I try to load http://financia.local/static/css/style.css in browser, it works.

Now I want to have nice icons, so I will add Font-awesome icons to Flask.

pipenv install Flask-FontAwesome

Then initialise Font-awesome in our __init__.py file.

from flask_fontawesome import FontAwesome

fa = FontAwesome(app)

Finally, load Font-awesome static files into HTML, most likely into my base HTML template.

{{ fontawesome_html() }}

Hmm. Fonts are not loaded.

I check generated HTML code with Chrome developer console.

Links to Font-awesome static files have been generated, but when I try to load them, files are not found.

<link href="/static/fontawesome/css/fontawesome.min.css?version=5.3.1" rel="stylesheetโ€>
<link href="/static/fontawesome/css/solid.min.css?version=5.3.1" rel="stylesheetโ€>

Right, I have to manually download those files from official Font-awesome website and copy paste files into path mentioned above.

Now it works.

Next I want to use Font-awesome icon as a tooltip.

You hover your cursor over icon and a text container appears above icon.

Because I user plain Bootstrap 4 HTML elements without any javascript, I need to use JQuery to make tooltips dynamic.

<script type="text/javascript">
    $(function () {

This should take care of hovering thing.

But it is not.

What about pointing JQuery to data-toggle parameter as demonstrated in Bootstrap 4 documentation.

<script type="text/javascript">
    $(function () {

Now it works.

Next, I want to display images in Jinja2 templates. There is a Jinja2 tag for that.

<img src="{{ url_for('static', filename=/static/logo.jpg) }}" class="rounded" alt="company">

Damn, no image found.

Img tag above somehow generated weird image source path.

<img src="/static//static/images/logo.jpg" class="rounded" alt="companyโ€>

Okay, let’s remove /static/ from image path.

Now image is displayed, but it does not fit parent div element.

Bootstrap 4 documentation says I should apply img-fluid CSS class, which fixed the issue.

I am exhausted, but I would like to do one last thing.

Left join another table and display left joined data in Jinja2 template.

First, I need to edit ORM query.

products = db.session.query(Product, Company, ProductType).join(Company, Company.id == Product.company_id).join(ProductType, ProductType.id == Product.product_type_id).all()

Refreshing web page throws internal server error.

Gunicorn logs reveals the root cause.

{% for product, company in products %}
ValueError: too many values to unpack (expected 2)

I forgot to edit my Jinja2 template loop tag with left joined table.

{% for product, company, product_type in products %}


Today was a productive day. Querying and displaying data works. Loading and displaying static files works too.

In the future, I will continue my development in silence if you don’t mind.

Now it is only about designing webpage with Bootstrap 4 components, which is boring.

But if I face interesting roadblock, I promise I will write about it, so you can learn from my mistakes.

Thanks for reading and see ya next time.

Share it!