Flask - A list of useful “HOW TO’s”
Tags: webdev, flask, python, appseed
Published: 2020-12-22 19:27:02

---
title: Flask - A list of useful “HOW TO’s”
published: true
description: A shortlist with useful hints and features that might help developers code faster a Flask project: DEBUG project, authentication, migrations, logging
tags: webdev, flask, python, appseed
canonical_url: https://blog.appseed.us/flask-how-to-code-simple-tasks/
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8weq86tv8xi5c5jqt00x.jpg
---
Hello Coders,

This article presents a shortlist with useful hints and features that might help developers code faster a **Flask** project. For newcomers, **[Flask](https://appseed.us/apps/flask/)** is a lightweight WSGI web application framework designed to get started quickly and easily, with the ability to scale up to complex applications.

> *Thanks for reading!* - Content provided by **[App Generator](https://appseed.us/)**.

---

- ✨ Section 1# - How to `code a simple App` in Flask
- ✨ Section 2# - `How to structure` your project
- ✨ Section 3# - How to `enable DEBUG`
- ✨ Section 4# - How to `set up SQLAlchemy`
- ✨ Section 5# - How to `use the Flask CLI`
- ✨ Section 6# - How to `migrate a Database`
- ✨ Section 7# - How to define and `use a form`
- ✨ Section 8# - How to `implement authentication`
- ✨ Section 9# - How to read `POST data`
- ✨ Section 10# - How to `redirect in Flask`
- ✨ Section 11# - `Logging` in Flask
- ✨ Section 12# - How to `return JSON` in Flask
- ✨ Section 13# - How to `enable CORS`
- ✨ Section 14# - Access the `app` object anywhere in our project
- ✨ Section 15# - A curated index with **[Free Dashboards](https://appseed.us/admin-dashboards/open-source/)** 
  - 🔥 [Flask Soft UI](https://appseed.us/product/soft-ui-dashboard/flask/) - Bootstrap 5 Dashboard
  - 🔥 [Flask Pixel UI Kit](https://appseed.us/product/pixel-bootstrap/flask/) - Bootstrap5 UI Kit
  - 🔥 [Datta Able Flask](https://appseed.us/product/datta-able/flask/)- colorful BS4 Design
  - 🔥 [Flask Bootstrap 5 Volt](https://appseed.us/product/volt-dashboard/flask/) - Bootstrap 5 design
  - 🔥 [Flask Dashboard Black](https://appseed.us/product/black-dashboard/flask/) - Dark-themed dashboard

---

Ok, let's get back to the real content - the first one is pretty basic and explains how to code a minimal Flask app in less than 1 minute (you need to type fast and have Python3 installed).  

---

## ✨ **1# - [Flask](https://appseed.us/apps/flask/), a minimal app**

Open a terminal and install Flask using PIP:

```bash
$ pip install Flask
```

Use your preferred editor to create a file called `hello.py`:

```python
from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello():
    return f'Hello from Flask!'
```

Once the file is saved, let's start the app:

```bash
$ env FLASK_APP=hello.py flask run
 * Serving Flask app "hello"
 * Running on http://127.0.0.1:5000/
```

By visiting the app in the browser we should see "Hello from Flask" message.

---

## ✨ **2# - How to structure your project**

Being such a lightweight framework, **Flask** comes with great flexibility regarding the codebase structure of a project. The one suggested in this article has been used in many Flask starters generated by the AppSeed platform but we are pretty sure there are many other good configurations published on Github or private blogs.

```bash
< PROJECT ROOT >
   |
   |-- app/__init__.py
   |-- app/
   |    |-- static/
   |    |    |-- <css, JS, images>         # CSS files, Javascripts files
   |    |
   |    |-- templates/
   |    |    |
   |    |    |-- includes/                 # Page chunks, components
   |    |    |    |
   |    |    |    |-- navigation.html      # Top bar
   |    |    |    |-- sidebar.html         # Left sidebar
   |    |    |    |-- scripts.html         # JS scripts common to all pages
   |    |    |    |-- footer.html          # The common footer
   |    |    |
   |    |    |-- layouts/                  # App Layouts (the master pages)
   |    |    |    |
   |    |    |    |-- base.html            # Used by common pages like index, UI
   |    |    |    |-- base-fullscreen.html # Used by auth pages (login, register)
   |    |    |
   |    |    |-- accounts/                 # Auth Pages (login, register)
   |    |    |    |
   |    |    |    |-- login.html           # Use layout `base-fullscreen.html`
   |    |    |    |-- register.html        # Use layout `base-fullscreen.html`  
   |    |    |
   |    |  index.html                      # The default page
   |    |  page-404.html                   # Error 404 page (page not found)
   |    |  page-500.html                   # Error 500 page (server error)
   |    |    *.html                        # All other pages provided by the UI Kit
   |
   |-- requirements.txt
   |
   |-- run.py
   |
   |-- ************************************************************************
```

The relevant files:

- `run.py` - the entry point used to start the application
- `requirements.txt` - a file that specifies all dependencies (for now is just Flask)
- `app` - the application folder where we will add our code
- `app/__init__.py` - This file is required to let us use the app as a Python Package
- `app/static` - this folder will contain design assets: JS, CSS, and images.
- `templates` - the directory with pages, layouts, and components used by Flask to generate some nice pages for us

---

## ✨ **3# - How to enable DEBUG**

Sometimes during our development we need to investigate errors in deep by checking the variables values, freeze the application execution and inspect the context or visualize a filtered products list in the user shopping cart. We can achieve this in two ways:

- using logs and inject print() statements all over the place
- using a Debugger and gain full control over the app without writing non-functional code in all controllers and helpers.

Flask comes with a [Built-in Debugger](https://flask.palletsprojects.com/en/master/debugging/#the-built-in-debugger) that allows us to inspect in deep application runtime execution. Flask automatically detects and enable the debugger by scanning the application environment:

```bash
$ export FLASK_ENV=development
$ flask run
```

When running from Python code, the app object accepts the debug variable as an argument:

```python
app.run(debug=True)
```

At this point, app should run in DEBUG more. Another useful option is to use the **debugger toolbar plugin**.

Adding an external [Debugger Toolbar](https://flask-debugtoolbar.readthedocs.io/en/latest/)

This plugin provides useful runtime information like HTTP Headers, configuration, rendered templates, and SqlAlchemy queries executed during requests.

To enable these features is pretty easy. First, we need to install the plugin (via PIP).

```bash
$ pip install flask-debugtoolbar
```

The next step is to use the extension over our Flask app:

```python
from flask import Flask
from flask_debugtoolbar import DebugToolbarExtension

app = Flask(__name__)

# the toolbar is only enabled in debug mode:
app.debug = True

# set a 'SECRET_KEY' to enable the Flask session cookies
app.config['SECRET_KEY'] = '<replace with a secret key>'

toolbar = DebugToolbarExtension(app)  # <--- NEW
```

If your product uses **app-factory pattern** to construct the Flask application, please use this code snippet:

```bash
...
# Initialize the Debug Toolbar
toolbar = DebugToolbarExtension()  # <--- NEW

# Make sure the app has DEBUG enable 
app = create_app()

# Inject the toolbar object in the Flask app object
toolbar.init_app(app)    # <--- NEW
...
```

---

> For more information related to Debugging in Flask, please access

- [Debugging Application Errors](https://flask.palletsprojects.com/en/master/debugging/#debugging-application-errors) - Flask documentation
- [Debugger Toolbar](https://flask-debugtoolbar.readthedocs.io/en/latest/) - aka Flask-DebugToolbar module  

---

## ✨ **4# - How to set up Flask-SQLAlchemy**

Flask-SQLAlchemy is a wrapper over the popular SQLAlchemy Python toolkit that empowers developers to manage a database using an object-oriented approach.

The setup required by Flask-SqlAlchemy is minimal:

```bash
$ pip3 install flask_sqlalchemy
```

Once the package is installed, we can use it in the source code:

```python
from flask import Flask

# Import SQLAlchemy
from flask_sqlalchemy import SQLAlchemy 

app = Flask(__name__)

# Define the database
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db'

# Inject SQLAlchemy magic 
db = SQLAlchemy(app)

# Sample model handled by SqlAlchemy  
class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)

    def __repr__(self):
        return '<User %r>' % self.username
```

To effectively create *User* table in the database, we need to use the Flask CLI (see the next section)  

---

> More SQLAlchemy resources

- [SQLAlchemy](https://www.sqlalchemy.org/) - toolkit page
- [Flask-SQLAlchemy](https://flask-sqlalchemy.palletsprojects.com/en/2.x/quickstart/) - Flask wrapper documentation  

---

## ✨ **5# - How to use the Flask CLI**

To use the Flask CLI, `FLASK_APP` environment variable should point to the application bootstrap script. Once we have this variable present in the working environment, we can launch the Flask console and interact with our application in a different way:

```bash
$ export FLASK_APP=app # adjust to match your entry point
$ flask shell
```

Using the CLI we can create the table defined in the previous section:

```bash
$ flask shell
>>> from app import db # 
>>> db.create_all()    # All tables are created
```

Using the CLI we can select and update users (or any other defined tables) as well:

```bash
$ flask shell
>>> from app import User
>>> User.query.all()
[<User u'admin'>, <User u'guest'>]
```

---

> For more resources, please access:

- [Flask CLI](https://flask.palletsprojects.com/en/1.1.x/cli/) - module documentation
- [Define custom commands](https://flask.palletsprojects.com/en/1.1.x/cli/#custom-commands) - a comprehensive section on this topic

---

## ✨ **6# - How to migrate a Database**

A migration means our database has changed:

- New table added
- The existing table is updated with a new column
- The type of an existing column has changed. For instance, we have a column that stores 100 characters and we need to extend it to 500.

To safely update the database, we need to "migrate" to the new structure. The Flask plugin that saves us from doing the dirty work is [Flask Migrate](https://flask-migrate.readthedocs.io/en/latest/).

```bash
$ pip install Flask-Migrate
```

To effectively work, Flask-Migrate must be injected in the Flask object:

```python
...
app = Flask(__name__)
...
migrate = Migrate(app, db) # <- The magic line
```

If we execute the migration for the first time, we should run:

```bash
$ # This will create the migrations folder
$ flask db init
```

Let's update the **User** model with a new field: **role**

```python
# Sample model handled by SqlAlchemy  
class User(db.Model):
    id       = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)
    email    = db.Column(db.String(120), unique=True, nullable=False)
    
    # The new field 
    role     = db.Column(db.Integer, primary_key=False)
```

To update the database, two steps are required: generate the SQL according to our change and apply it on the database.

**Generate the SQL**

```bash
$ flask db migrate
```

**Update the Database** - using the SQL generated in the previous step

```bash
$ flask db upgrade
```

At this point, we can inspect the table to visualize the presence of the role column and use it in our code.

---

> Resources

- [Flask-Migrate](https://flask-migrate.readthedocs.io/en/latest/) - the official module documentation
- [Flask – Setting up Postgres, SQLAlchemy, and Alembic](https://realpython.com/flask-by-example-part-2-postgres-sqlalchemy-and-alembic/) - a nice tutorial on this hot topic

---

## ✨ **7# - How to define and use a form**

Flask assists us a lot regarding forms via a dedicated library: flask_wtf/[FlaskForm](https://flask-wtf.readthedocs.io/en/stable/form.html). We can easily define, secure, and validate forms using this package.

Here is the **definition of a Login form**:

```python
from flask_wtf          import FlaskForm
from wtforms            import StringField, PasswordField

class LoginForm(FlaskForm):
	username    = StringField  (u'Username'  , validators=[DataRequired()])
	password    = PasswordField(u'Password'  , validators=[DataRequired()])
```

As mentioned, FlaskForm comes with re-defined types and validators for the password, mandatory fields check, email, and much more.

The view (aka the page) that use it:

```html
<form role="form" method="post" action="">
    {{ form.username(placeholder="Username") }}
    {{ form.password(placeholder="Password",type="password") }}
</form>
```
For newcomers, a simplified CSRF mechanism is presented below:

- Server generates the CRSF Token
- Form is built and sent to the client browser along with the token
- The user fills and submits the form
- The server receives a new POST request and check the CSRF token authenticity
- If the token is not validated request is rejected with a 403 (not authorized) status

---

> More resources

- [Creating Forms](https://flask-wtf.readthedocs.io/en/stable/form.html) in Flask
- [CSRF Protection in Flask](https://flask-wtf.readthedocs.io/en/stable/csrf.html) - how to use it

---

## ✨ **8# - How to authenticate in Flask**

Flask-Login provides user session management for Flask. It handles the common tasks of logging in, logging out, and remembering users’ sessions.

Let's highlight the code to integrate Flask-Login in a real application.

**Update your User model** to inherit the [UserMixin](https://flask-login.readthedocs.io/en/latest/#flask_login.UserMixin) class. This is necessary because Flask expects a minimum set of handlers to be implemented by the user model: **is_authenticated**, **is_active**, **get_id**. To skip over this work, **UserMixin** class saves the day for us.

```python
from app         import db
from flask_login import UserMixin

# User model uses UserMixin as parent class 
class User(UserMixin, db.Model):

    id       = db.Column(db.Integer,     primary_key=True)
    user     = db.Column(db.String(64),  unique = True)
    email    = db.Column(db.String(120), unique = True)
    password = db.Column(db.String(500))
```

The next step is to define **user_loader** a method used by [Login-Manager](https://flask-login.readthedocs.io/en/latest/#flask_login.LoginManager) to identify the current authenticated user information: id, email and all other fields provided by the User class.

```python
...
# provide login manager with load_user callback
@lm.user_loader
def load_user(user_id):
    return User.query.get(int(user_id))
...
```

Once we have the User table updated in the database, we can successfully login.

**The login view** (aka login page): 

```html
...
<form method="post" action="" class="mt-4">
    {{ form.hidden_tag() }}
    {{ form.username(class="form-control") }}
    {{ form.password(class="form-control", type="password") }}
    
    <button type="submit" name="login">Sign in</button>
</form> 
```

Once the user fills username and the password, all information is sent to the server via a POST request.

**Login  - The controller code**

```python
# Authenticate user
@app.route('/login.html', methods=['GET', 'POST'])
def login():
    
    # Declare the login form
    form = LoginForm(request.form)
	
    # The information returned to the user
    msg = "Your cool!"

    # Apply all validations defined in the form
    if form.validate_on_submit():

        # recover form information
        username = request.form.get('username', '', type=str)
        password = request.form.get('password', '', type=str) 

        # recover the user from database using username (unique information)
        user = User.query.filter_by(user=username).first()

		# If the user is found, validate the password
        if user:
            
            # BC = BCrypt library 
            if bc.check_password_hash(user.password, password):
                # The user is now authenticated
            	login_user(user)
            else:
                msg = "Wrong password. Please try again."
        else:
            msg = "Unknown user"

    return render_template( 'accounts/login.html', form=form, msg=msg )
```

The controller flow explained:

- Local variable **form** is initialized using the request form (sent by the user)
- If the form is valid (user and password are present) the code extracts the values
- Select the user from the database using the name
- Check the password by comparing the database value with the one provided by the user and hashed by the BCrypt library.
- If all is good, the user session is created via **"login_user()"** handler
- Error cases are flagged with a message to inform the user what was wrong.

---

> Flask authentication resources:

- [Flask-Login](https://flask-login.readthedocs.io/en/latest/) - the concerned module
- [LoginManager](https://flask-login.readthedocs.io/en/latest/#flask_login.LoginManager) class definition

---

## ✨ **9# - How to read POST data**

For newcomers, POST and GET are different methods used to submit information to a server. During a GET request, the variables are appended to the page URL:

```html
GET/login.html?user=Biden&pass=MAGA2020 
```

POST requests use the request body to bundle the information submitted by the user.

In both cases, we can easily read POST and GET parameters with Flask via the [request](https://flask.palletsprojects.com/en/1.1.x/api/#flask.Request) object. Here is a list of request objects that we can refer to extract the information:

- **request.args**: the key/value pairs in the URL query string
- **request.form**: the key/value pairs in the body, from a HTML post form
- **request.json**: parsed JSON data

---

**A real sample** - used to handle registration flow

```python
@app.route('/register.html', methods=['GET', 'POST'])
def register():
    
    # declare the Registration Form
    form = RegisterForm(request.form)
	
    # request is GET - just display the form
    if request.method == 'GET': 

        return render_template( 'accounts/register.html', form=form, msg=msg )

    # Here we have a POST request
    if form.validate_on_submit():

        # READ information from a POST request
        username = request.form.get('username', '', type=str)
        password = request.form.get('password', '', type=str) 
        email    = request.form.get('email'   , '', type=str) 
```

As mentioned above, the composite **[request.form](https://flask.palletsprojects.com/api/#flask.Request.form)** provides the form fields in key/value pairs bundled in the request body.

---

> More information on this topic:

- [Flask request Args](https://flask.palletsprojects.com/en/1.1.x/api/#flask.Request.args) - object information
- [Get the data received in a Flask request](https://stackoverflow.com/questions/10434599/get-the-data-received-in-a-flask-request) - Related StackOverflow topic

---

## ✨ **10# - How to redirect in Flask**

This is a simple one.  Flask exposes a "redirect" handler to keep us lazy:

```python

import os
from flask import Flask,redirect

app = Flask(__name__)

@app.route('/')
def not_me():
    
    # redirect to another page
    return redirect("/register")

    # redirect to external page
    return redirect("https://google.com")

    # redirect with HTTP code
    return redirect("https://google.com", code=301)
```

---

> Resources:

- [Flask redirect](https://flask.palletsprojects.com/en/1.1.x/api/#flask.redirect) - handler docs
- [Flask redirect Example](https://www.fullstackpython.com/flask-redirect-examples.html) - tutorial provided by Full-Stack Python

---

## ✨ **11# - Logging in Flask**

Flask uses the native Python logging system (no configuration required). To log a message during a request, we need to call the logger interface and set the message we want to be visible in logs:

```python
from flask import Flask
import logging

app = Flask(__name__)

logging.basicConfig(level=logging.DEBUG)

@app.route('/')
def hello():
    app.logger.info('Logging is up!')
    return 'Hello World!'

if __name__ == '__main__':
    app.run()
```

By running the app, we should see the logging message in the console:

```bash
* Serving Flask app "app.py"
* Environment: development
INFO:werkzeug: * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
INFO:flask.app:Logging is up
INFO:werkzeug:127.0.0.1 - - [01/Jun/2019 17:03:09] "GET / HTTP/1.1" 200 -
```

Logs might be useful when we want to trace runtime errors in production or save other relevant events in the logs for the application owner.  

The above sample will push the log to the console but we can easily push messages to a file:

```python
from flask import Flask
import logging

app = Flask(__name__)

logging.basicConfig(filename='app.log', level=logging.DEBUG)

@app.route('/')
def hello():
    app.logger.info('Logging is up!')
    return 'Hello World!'

if __name__ == '__main__':
    app.run()
```

After a first request, a new file named "app.log" should be created with our log message as content.

---

> Flask logging resources

- [Flask Logging](https://flask.palletsprojects.com/en/1.1.x/logging/) - the official module documentation
- [Flask Logging - Get starter quickly](https://www.scalyr.com/blog/getting-started-quickly-with-flask-logging/) - a nice tutorial.

---

## ✨ **12# - How to return JSON**

Flask comes with native support for JSON management via [jsonify](https://flask.palletsprojects.com/en/1.1.x/api/#flask.json.jsonify) interface. Let's take a look at this self-descriptive sample:

```python
from flask import jsonify

@app.route('/_get_current_user')
def get_json():
    return jsonify(
        message="Hello",
        from="from JSON"
    )
```

The output returned in the browser should be as below:

```json
{
    "message": "Hello",
    "from": "from JSON"
}
```

---

Something useful: let's return a registered user using JSON format:

```python
from flask import jsonify

@app.route('/user_json')
def get_json():
    
    user = User.query.filter_by(username='testme').first()
    
    # Using the user object (without __dict__) will generate a runtime error 
    # TypeError: 'user' is not JSON serializable
    return jsonify( user.__dict__ )
```

The response should contain all fields defined in the User table:

```json
{
    "id": "1",
    "username": "testme",
    "email":"test@google.com"
}
```

---


> More resources:

- [Flask jsonify](https://flask.palletsprojects.com/en/1.1.x/api/#flask.json.jsonify) - class documentation
- [Serializing class instance to JSON](https://stackoverflow.com/questions/10252010/serializing-class-instance-to-json) - related StackOverflow topic

---

## ✨ **13# - How to enable CORS in Flask**

This feature is useful when our Flask backend is consumed by decoupled entities like a mobile UI interface, external systems that push or request the information provided by the Flask backend.

As usual, Flask has a module for this [flask-cors](https://flask-cors.readthedocs.io/en/latest/).

```bash
$ Install the module via PIP
$ pip install -U flask-cors
```

Let's take a look at the sample provided in the official docs:

```python
from flask import Flask
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

@app.route("/")
def helloWorld():
  return "Hello, cross-origin-world!"
```

We can also isolate CORS for specific paths like **/api/*:**

```python
app = Flask(__name__)
cors = CORS(app, resources={r"/api/*": {"origins": "*"}})

@app.route("/api/v1/users")
def list_users():
  return "user example"
```

---

> CORS Resources

- [Flask-CORS](https://flask-cors.readthedocs.io/en/latest/) - official documentation
- [What is CORS](https://www.codecademy.com/articles/what-is-cors) - a tutorial provided by Codecademy

---

## ✨ **14# - Access the `app`** object

When we are coding a Flask project using more than one file and the complexity rises, we might need to access the `Flask app` constructed by the project during the initialization. We can achieve this pretty easily by accessing `current_app` object provided by Flask itself. 

```python
from flask import Flask
from flask import current_app
from flask_cors import CORS

# This is the constructed bject
app = Flask(__name__) 

current_app # here is the reference to "app" object
            # we can do this in any file
```

---

## ✨ **15# - Open-source Samples**

All projects mentioned below can be downloaded without a registration lock and used for unlimited hobby & commercial projects. 

---

### 🔥 [Flask Soft UI](https://appseed.us/product/soft-ui-dashboard/flask/)

Free dashboard crafted in **Flask** Framework, designed for those who like bold elements and beautiful websites, **[Soft UI](https://appseed.us/ui-kit/soft-ui-design-system)** Dashboard is ready to help you create stunning websites and webapps. 

> **[Flask Soft UI](https://appseed.us/product/soft-ui-dashboard/flask/) - product page** (contains DEMO & sources)

![Flask Soft UI Dashboard - Open-source seed project crafted in Flask.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/re7v7rpj4nf229v6xpd3.png)
 
---

### 🔥 [Flask Pixel UI Kit](https://appseed.us/product/pixel-bootstrap/flask/)

Open-Source Flask starter coded with basic modules, database, ORM and deployment scripts on top of Pixel Lite UI Kit, a fully responsive and modern Bootstrap 5 UI Kit that will help you build creative and professional websites. The Flask codebase comes with basic modules, database, ORM and deployment scripts.

> **[Flask Pixel UI Kit](https://appseed.us/product/pixel-bootstrap/flask/) - product page** (contains DEMO & sources)

![Flask Pixel UI Kit - Open-source Flask seed project.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fiinj74axxsk4badurmu.png)

---

### 🔥 [Datta Able Flask](https://appseed.us/product/datta-able/flask/)

Datta Able Bootstrap Lite is the most stylized Bootstrap 4 Lite Admin Template, around all other Lite/Free admin templates in the market. It comes with high feature-rich pages and components with fully developer-centric code. Before developing Datta Able our key points were performance and design.

> **[Datta Able Flask](https://appseed.us/product/datta-able/flask/) - product page** (contains DEMO & sources)

![Datta Able Flask - Open-source Flask seed project.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7tacs6rsg1j5dx5rb2oy.png)
 
---

### 🔥 [Flask Bootstrap 5 Volt](https://appseed.us/product/volt-dashboard/flask/)

Volt Dashboard is a free and open source Bootstrap 5) dashboard template featuring over 100 components, 11 example pages and 3 plugins with Vanilla JS. There are more than 100 free Bootstrap 5 components included some of them being buttons, alerts, modals, datepickers and so on.

> **[Flask Bootstrap 5 Volt](https://appseed.us/product/volt-dashboard/flask/) - product page** (contains DEMO & sources)

![Flask Bootstrap 5 Volt - Open-source Flask seed project.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6us8w4uoan3kwio6c5hk.png)
 
---

### 🔥 [Flask Dashboard Black](https://appseed.us/product/black-dashboard/flask/)

**Flask Black Dashboard** is an open-source [Flask Dashboard](https://appseed.us/admin-dashboards/flask) generated by AppSeed on top of a modern dark-themed UI. **Black Dashboard** is a beautiful Bootstrap 4 Admin Dashboard with a huge number of components built to fit together and look amazing. 

> **[Flask Dashboard Black](https://appseed.us/product/black-dashboard/flask/) - product page** (contains DEMO & sources)

![Flask Dashboard Black - Free starter.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7ejj8uoprh02k9l25cws.png)

---

> **Thanks for reading!** For more resources, feel free to access:

- 👉 More [Flask Dashboards](https://appseed.us/admin-dashboards/flask/) crafted in Django, Flask, and `React`
- 👉 More [Flask Apps](https://appseed.us/apps/flask/) - free & PAID