Shopyo: Enhance Your Flask by Exploring An Advanced Flask App

Shopyo: Enhance Your Flask by Exploring An Advanced Flask App

Shopyo is an Open Source Flask-based, Python-powered inventory solution and upcoming point of sales. It’s aim is to help small business owners get a nice Python-based product with essential amenities for their businesses.

An empty Shopyo project at the very least makes a great Flask base.

The Tech Stack

A peek at Shopyo’s requirements.txt gives

  • flask_sqlalchemy

flask_sqlalchemy is a wrapper around SQLAlchemy, a popular Python ORM. An ORM allows you to define your SQL tables without the need to write SQL codes. You just define models and the table is created for you. A typical model looks like this:

  • flask_migrate

flask_migrate is used to migrate your models. If you change your models by adding a new field, the change is not reflected in your database. That’s why you need to apply migrations. It is a wrapper around Alembic, a popular migration package.

  • flask_marshmallow
  • marshmallow_sqlalchemy

Marshmallow is a project that allows you to create REST Apis. flask_marshmallow allows the easy integration of marshmallow with Flask and marshmallow_sqlalchemy is a required package that goes along.

  • flask_script

Though deprecated by Flask’s official command line utitlity, flask_script allows you to create scripts to manage your Flask app easily.

  • flask_login

Flask login allows you to add authentication to your app.

  • Flask-WTF

A package that allows you to create forms. We use it to prevent CSRF (pronounced sea surf) attacks. It basically ensures that you don’t tamper with a webpage then try to send it to someone else expecting it to work

  • requests

A package to make web requests and pull in urls easily. You can view a tutorial about it here

Terms Explained


A model defines your table

creates a table named settings with fields named setting and value


A template is an html file with spaces left for values. {% and {{ have special meaning. {{1 + 1}} will display 2 when rendered. Similarly {{x + 1}} will evaluate the expression before rendering.

let’s take this snippet

Tells that we are inheriting from base.html

This eases our life by not copying whole <link> or <script> codes for example or not recopying the header/footer

allows us to define our head and body respectively.

Views and blueprint

A view file has lots of routes and what happens when such a route is found. This is the settings view file for example

Here is a breaking down:

  • Blueprint

Allows us to create blueprints. More on that further on

  • render_template

return render_template(filename) returns the rendered html

  • request

refers to the incoming web request by which we can check for GET or POST methods

  • redirect

redirects to another url

  • jsonify

returns a string or dictionary as JSON response

addon contains the following:

Tells us to go to views folder -> settings folder -> models file contains base_context which returns just a dictionary

We copy so as not to let additions be global. Render templates accepts the variables to be rendered as keywords. But those 3 variables are rendered everywhere so, instead of copy paste each time, we just added them beforehand to the dictionary.

This tells that whatever urls starts with /settings will be dealt with in this file

is actually for the url /settings/abc

Context is just a dictionary

passes the settings variable which the for loop in the template makes use of

By the way,

is the same as

Register blueprints

in you will see

which adds the views of the settings folder to the app.

Configuration management

in we see

then in

then further down

so, if we put in ‘production’ it will load the production configs.

As info, creating apps this way (app = …) is called the App Factory pattern

allows us to pass in normal Alembic migration commands

normal alembic commands run like:

but using the above code, we automatically get

similarly this:

allows us to have


This was written as part of the Shopyo docs but makes a nice Flask post by the way!

If you did not understand something, please ping me at

Lives in Mauritius, cruising python waters for now.