How to structure Flask application for larger projects

Flask application

Many Flask beginners get confused when building an architecture for bigger projects. After finishing simple one-page examples, then don’t get where to jump. People came from Django background are already familiar with DRY application architecture and feel like Flask is not good for big projects.

But no need to worry. The real beauty of Flask lies in its flexibility. You can build a Django-like architecture in minutes or you can customize as per your own taste (which you can’t in Django). In this article, we will see two idle project skeletons, one will be minimal for small to medium projects while other will be reusable like Django, designed for bigger projects.

Flask Minimal Architecture

In minimal architecture, we will divide our app in below components –

  • routes(a.k.a. urls)
  • controllers(a.k.a. views)
  • data models
  • web forms
  • client side files like html templates, css stylesheets, JS scripts (a.k.a UI)
  • unit test cases

Skeleton

Final architecture will be like below.

myproject
├── myproject
│   ├── __init__.py
│   ├── routes.py
│   ├── controllers.py
│   ├── models.py
│   ├── extensions.py
│   ├── forms.py
│   ├── commands.py
│   └── ui
│       ├── static
│       │   ├── css
│       │   │   └── styles.css
│       │   └── js
│       │       └── custom.js
│       └── templates
│           └── index.html
├── tests
│   ├── __init__.py
│   ├── conftest.py
│   └── test_controllers.py
├── config.py
├── instance
│   └── config.py
├── wsgi.py
├── requirements.txt
└── README.md

Now lets go through usage and content of each file.

  • myproject/myproject/init.py – Your project starts here. Blueprints, extensions, commands and all other fancy stuff will be defined in their own modules. But all those components will be hooked up together here. See application-factories.
  • myproject/myproject/routes.py – These are your URLs grouped together using blueprints. They are pointed to controllers.
  • myproject/myproject/controllers.py – Define your controllers here to manipulate views and database. Similar to views.py in django. So flow will be url => controller => template/database.
  • myproject/myproject/extensions.py – Instantiate flask extensions here so those can be easily accessed in other modules. Extensions can be initialized in myproject/myproject/__init__.py also. Keeping them separate, will look clean. Important point is, after you INSTANTIATE extension here, you need to INITIATE it again in myproject/myproject/__init__.py/create_app. You can see example format in comments once app is created.
  • myproject/myproject/forms.py – Create your http forms here. See wtforms
  • myproject/myproject/models.py – Create your database models here. See flask-sqlalchemy. Make sure to enable related extension for this. Database url will be configured in configuration files. See below.
  • myproject/myproject/commands.py – Custom terminal commands to ease your workflow. See flask-cli
  • myproject/myproject/ui/static – keep your static files like css, js, media here.
  • myproject/myproject/ui/templates – keep your http templates here.
  • myproject/config.py – Project permanent configuration. This should be committed in version control tool. Similar to settings.py in django.
  • myproject/instance/config.py – Project temporary config like secrets etc. It MUST NOT be committed in version control tool. See instance-config.
  • myproject/wsgi.py – wsgi module to integrate app with web servers like apache, gunicorn. See mod_wsgi.
  • myproject/requirements.txt – Python modules used in project.
  • myproject/README.md – Information about project.

Extending Minimal Application

Even though this structure looks minimal, we can extend it gradually by again grouping individual functionalities in components. e.g. we can convert router.py to directory and can add routes of each functionality in separate module. See below structure –

myproject
├── myproject
│   ├── commands.py
│   ├── controllers
│   │   ├── auth_controllers.py
│   │   ├── blog_controllers.py
│   │   ├── comments_controllers.py
│   │   └── __init__.py
│   ├── forms
│   │   ├── auth_forms.py
│   │   ├── blog_forms.py
│   │   ├── comments_forms.py
│   │   └── __init__.py
│   ├── __init__.py
│   ├── models
│   │   ├── auth_models.py
│   │   ├── blog_models.py
│   │   └── __init__.py
│   ├── routes
│   │   ├── auth_routes.py
│   │   ├── blog_routes.py
│   │   └── __init__.py
│   └── ui
│       ├── static
│       │   ├── css
│       │   └── js
│       └── templates
├── config.py
├── instance
│   └── config.py
├── wsgi.py 
├── requirements.py
└── README.md 

Pros

  • Easy to manage architecture by avoiding jumbling of files
  • Easy to search related code
  • Good for small to medium projects
  • Grouping based on standard web components

Cons

  • Difficult to write re-usable code.

Cookiecutter Template to start project

Using cookiecutter tool, you can easily create this architecture in few seconds (similar to django startproject) . Template for this architecture is at cookicutter-flask-minimal. For usage see README.md

Flask Reusable Architecture

Django framework is very opinionated about project structure. DRY a.k.a. Don’t Repeat Yourself is a core of Django’s design philosophy. Django enforces developer to follow architecture based on reusable functionalities called apps. It is interesting concept. Our main app is broken into different re-usable small apps based on functionalities. Models, controllers and routes of particular functionality are grouped together to form this small application. So you can just plug it into another project whenever necessary.. The best example of such functionality is authentication.

Skeleton

Final architecture will be like below.

 myproject
 ├── myapp
 │   ├── __init__.py
 │   ├── extensions.py
 │   │
 │   ├── helpers
 │   │   ├── __init__.py
 │   │   ├── controllers.py
 │   │   ├── models.py
 │   │   └── commands.py
 │   │
 │   ├── auth
 │   │   ├── __init__.py
 │   │   ├── routes.py
 │   │   ├── controllers.py
 │   │   ├── models.py
 │   │   ├── forms.py
 │   │   └── commands.py
 │   │
 │   └── ui
 │       ├── static
 │       │   ├── css
 │       │   │   └── styles.css
 │       │   └── js
 │       │       └── custom.js
 │       │
 │       └── templates
 │           ├── 404.html
 │           ├── 500.html
 │           └── base.html
 │
 ├── tests
 │   ├── __init__.py
 │   ├── conftest.py
 │   │   
 │   └── auth
 │       ├── __init__.py
 │       └── test_controllers.py
 │
 ├── config.py
 ├── instance
 │   └── config.py
 ├── wsgi.py
 │
 ├── requirements.txt
 └── README.md 

This architecture is self-explanatory if you studied previous one. Modules are almost similar to previous architecture, only difference is in grouping. We just grouped common functionalities in myproject/helper package while auth related functionalities in myproject/auth package. Same goes with testcases too.

Pros

  • Using such architecture, we can build reusable apps and speed up new projects.

Cons

  • This kind of architecture is not much suitable for very small projects/API projects where functionalities are limited or of same type.
  • Many times functionalities are inter-connected with each other and need some experience for proper abstraction.

Cookiecutter Template to start project

Cookicutter template for this architecture can be found at cookicutter-flask. For usage see README.md

Conclusion

The real power of Flask lies in its flexibility. Flask can accommodate simple as well as complex projects with ease. In the end, whichever architecture you chose, always keep it consistent through out project.

Leave a Reply