Getting Started

Install Flask Unchained

Create a new directory and enter it:

mkdir hello-flask-unchained && cd hello-flask-unchained

The tutorial will assume you’re working from the hello-flask-unchained directory from now on. All commands are assumed to be run from this top-level project directory, and the file names at the top of each code block are also relative to this directory.

Next, let’s create a new virtualenv, install Flask Unchained into it, and activate it:

# create our virtualenv and activate it
python3 -m venv venv && . venv/bin/activate

# install flask-unchained
pip install "flask-unchained[dev]"

# reactivate the virtualenv so that pytest will work correctly
deactivate && . venv/bin/activate

Python Virtual Environments

There are other ways to create virtualenvs for Python, and if you have a different preferred method that’s fine, but you should always use a virtualenv by some way or another.

Project Layout

Just like Flask, Flask Unchained apps can be written either as a single file or in multiple files following a (configurable) naming convention. A large project might have a folder structure that looks like this:

├── app                 # your app bundle package
│   ├── admins          # model admins
│   ├── commands        # click groups/commands
│   ├── extensions      # extension instances
│   ├── models          # sqlalchemy models
│   ├── serializers     # marshmallow serializers (aka schemas)
│   ├── services        # dependency-injectable services
│   ├── tasks           # celery tasks
│   ├── templates       # jinja templates
│   ├── views           # controllers and resources
│   ├──
│   ├──       # app config
│   └──       # declarative routes
├── assets              # static assets to be handled by Webpack
│   ├── images
│   ├── scripts
│   └── styles
├── bundles             # third-party bundle extensions/overrides
│   └── security        # a customized/extended Security Bundle
│       ├── models
│       ├── serializers
│       ├── templates
│       └──
├── db
│   ├── fixtures        # sqlalchemy model fixtures (for seeding the dev db)
│   └── migrations      # alembic migrations (generated by flask-migrate)
├── static              # static assets (Webpack compiles to here, and Flask
│                       #  serves this folder at /static (by default))
├── templates           # the top-level templates folder
├── tests               # your pytest tests
├── webpack             # Webpack configs
└── # the flask unchained config

By the end of this tutorial, we’ll have built something very close. But for now, let’s start with the basics.

A Minimal Hello World App

The starting project layout of our hello world app is three files:


Let’s create them:


And the code:



from flask_unchained import AppBundle, Controller, route

class App(AppBundle):

class SiteController(Controller):
    def index(self):
        return 'Hello World!'

Whenever you create a new app in Flask Unchained, you start by creating a new “app bundle”: This is an overloaded term. The app bundle, conceptually, is your app. Literally, the app bundle is a subclass of AppBundle that must live in your app bundle’s module root ( here).

We can now start the development server with flask run and you should see your site running at http://localhost:5000:

flask run
 * Environment: development
 * Debug mode: on
 * Running on (Press CTRL+C to quit)

Let’s add a quick test before we continue.


class TestSiteController:
    def test_index(self, client):
        r = client.get('site_controller.index')
        assert r.status_code == 200
        assert r.html.count('Hello World!') == 1

Here, we’re using the HTTP client pytest fixture to request the URL for the endpoint "site_controller.index", verifying the response has a status code of 200, and lastly checking that the string "Hello World!" is in the response.

Let’s make sure it passes:

======================== test session starts ========================
platform linux -- Python 3.6.6, pytest-3.6.4, py-1.5.4, pluggy-0.7.1
rootdir: /home/user/dev/hello-flask-unchained, inifile:
plugins: flask-0.10.0, Flask-Unchained-0.8.0
collected 1 item .                                                   [100%]
======================== 1 passed in 0.18 seconds ====================

NOTE: If you get any errors, you may need to deactivate and reactivate your virtualenv if you haven’t already since installing pytest.

If you haven’t already, now would be a good time to initialize a git repo and make our first commit. Before we do that though, let’s add a .gitignore file to make sure we don’t commit anything that shouldn’t be.

# .gitignore


Initialize the repo and make our first commit:

git init
git add .

# review to make sure it's not going to do anything you don't want it to:
git status

git commit -m 'initial hello world commit'

OK, everything works, but this is about as basic as it gets. Let’s make things a bit more interesting by moving on to Views, Templates, and Static Assets.