• This repository has been archived on 13/Dec/2020
  • Stars
    star
    517
  • Rank 84,962 (Top 2 %)
  • Language
    Python
  • License
    MIT License
  • Created about 10 years ago
  • Updated over 6 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

This is how I structure my large Flask applications.

Flask-Large-Application-Example

PyPI Portal is a small demo app used as an example of a potentially large Flask application with several views and Celery tasks. This is how I structure my large Flask applications. In this README I'll explain my design choices with several aspects of the project.

For information on how to deploy this application to different production environments, visit the project's wiki.

[Build Status] (https://travis-ci.org/Robpol86/Flask-Large-Application-Example) [Coverage Status] (https://coveralls.io/r/Robpol86/Flask-Large-Application-Example)

Features

Some features I've included in this demo application are:

  • Tests are written for pytest.
  • Tasks/scripts/jobs are supported with Celery.
  • Any unhandled exceptions raised in views or Celery tasks are emailed to you from your production instance. The email is styled to look similar to the exceptions shown in development environments, but without the interactive console.
  • Message flashing is "powered by" Bootstrap Growl and I've also included Bootstrap Modals and Wells as flashed message containers. More about that in core/flash.py.

Directory Structure

β”œβ”€ pypi_portal/         # All application code in this directory.
β”‚  β”œβ”€ core/             # Shared/misc code goes in here as packages or modules.
β”‚  β”œβ”€ models/
β”‚  β”‚  β”œβ”€ fruit.py       # Holds several tables about a subject.
β”‚  β”‚  └─ vegetable.py
β”‚  β”‚
β”‚  β”œβ”€ static/
β”‚  β”‚  β”œβ”€ favicon.ico
β”‚  β”‚  └─ some_lib/
β”‚  β”‚     β”œβ”€ css/
β”‚  β”‚     β”‚  └─ some_lib.css
β”‚  β”‚     └─ js/
β”‚  β”‚        └─ some_lib.js
β”‚  β”‚
β”‚  β”œβ”€ tasks/          # Celery tasks (packages or modules).
β”‚  β”œβ”€ templates/      # Base templates used/included throughout the app.
β”‚  β”‚  β”œβ”€ 404.html
β”‚  β”‚  └─ base.html
β”‚  β”‚
β”‚  β”œβ”€ views/
β”‚  β”‚  β”œβ”€ view1/
β”‚  β”‚  β”‚  β”œβ”€ templates/              # Templates only used by view1.
β”‚  β”‚  β”‚  β”‚  └─ view1_section1.html  # Naming convention: package_module.html
β”‚  β”‚  β”‚  β”œβ”€ section1.py             # Each view module has its own blueprint.
β”‚  β”‚  β”‚  └─ section2.py
β”‚  β”‚  β”‚
β”‚  β”‚  β”œβ”€ view2/
β”‚  β”‚  └─ view3/
β”‚  β”‚
β”‚  β”œβ”€ application.py  # Flask create_app() factory.
β”‚  β”œβ”€ blueprints.py   # Define Flask blueprints and their URLs.
β”‚  β”œβ”€ config.py       # All configs for Flask, Celery, Prod, Dev, etc.
β”‚  β”œβ”€ extensions.py   # Instantiate SQLAlchemy, Celery, etc. Importable.
β”‚  └─ middleware.py   # Error handlers, template filters, other misc code.
β”‚
β”œβ”€ tests/                   # Tests are structured similar to the application.
β”‚  β”œβ”€ core/
β”‚  β”‚  └─ test_something.py
β”‚  β”œβ”€ tasks/
β”‚  └─ conftest.py
β”‚
└─ manage.py          # Main entry-point into the Flask/Celery application.

Design Choices

Blueprints

The first thing you may notice are where blueprints are defined. Flask applications usually define their blueprints inside view modules themselves, and must be imported in or after create_app(). URLs for blueprints are usually set in or after create_app() as well.

I've never liked defining blueprints in the views since according to pep8 the variables should be IN_ALL_CAPS (it's true that blueprints are still module-level in blueprints.py but since that file is 99% module-level variables I make a small exception to pep8 and keep it lower case), plus usually it's the only module-level variable in the file.

Instead I define blueprints in blueprints.py and import them in both views and application.py. While I'm at it, I "centralize" URL and module specifications in blueprints.py instead of having those two pieces of information in views and application.py.

Templates

This is another deviation from usual Flask applications. Instead of dumping all templates used by all views into one directory, I split it up into two classes: "common" and "per-view". This makes it way easier to determine which view a template is used in with a quick glance. In very large applications this is much more manageable, since having tens or even hundreds of templates in one directory is ugly.

First I have my common templates, located in the usual templates directory at the base of the application directory structure. Templates not tied to a specific view go here.

Then I have the per-view templates. Each view package will have its own templates directory. There is one problem though: Flask flattens the template's directory structure into one directory. templates/base.html and views/my_view/templates/base.html will collide. To get around this, templates inside a per-view template directory are formatted as packageName_moduleName.html (where packageName is my_view). When modules have a lot of templates just append to the filename (e.g. packageName_moduleName_feature.html).

Extensions

This isn't very unique but I'll cover it anyway. I've seen other projects follow this convention. The idea is to instantiate extensions such as SQLAlchemy here, but without any arguments (and without calling init_app()).

These may be imported by views/tasks and are also imported by application.py which is where init_app() is called.

Config

I elected to keep all configurations in this one file, instead of having different files for different environments (prod, stage, dev, etc). One important note is I also keep non-Flask configurations in the same file (e.g. Celery, SQLAlchemy, even hard-coded values). If you need to hard-code some data that's shared among different modules, I'd put it in config.py. If you need to hard-code data that's only used in one module (just one view for example), then I'd keep it in that module as a module-level variable.

I structure my config.py with several classes, inheriting from the previous one to avoid duplicating data.

Tests

The tests directory structure mirrors the application's. This makes it easy to group tests for specific views/modules. If a module such as core/email.py requires several tests, I would split them up into different test modules inside a package such as tests/core/email/test_feature1.py and so on.

More Repositories

1

terminaltables

Project no longer maintained.
Python
689
star
2

Flask-Celery-Helper

Celery support for Flask without breaking PyCharm inspections.
Python
151
star
3

colorclass

Colorful worry-free console applications for Linux, Mac OS X, and Windows.
Python
58
star
4

libnl

Pure Python port of the Netlink protocol library suite.
Python
50
star
5

makemkv

Automated headless DVD/Bluray backups with MakeMKV from Docker.
Python
28
star
6

robpol86.com

My personal website.
Python
16
star
7

etaprogress

Easy to use ETA calculation and progress bar library.
Python
14
star
8

sphinx-disqus

Embed Disqus comments in Sphinx documents/pages.
Python
11
star
9

appveyor-artifacts

Download artifacts from AppVeyor builds of the same commit/pull request.
Python
10
star
10

logrus-custom-formatter

Customizable Logrus formatter similar in style to Python's logging.Formatter.
Go
10
star
11

influxdb

Docker-compose stack for InfluxDB, Grafana, and Cronitor
Shell
8
star
12

UnofficialDDNS

An unofficial dynamic DNS (DDNS) service for Name.com domains.
C#
8
star
13

Flask-Redis-Helper

Redis support for Flask without breaking PyCharm inspections.
Python
6
star
14

docoptcfg

docopt wrapper adding config file and environment variable support.
Python
5
star
15

flake8-pydocstyle

Abandoned
Python
5
star
16

Flask-Large-App-Example-2

Another example of a large Flask application.
JavaScript
4
star
17

EImage

Display images from image hosting services as if they were stored locally.
PHP
3
star
18

wifipy

Pure Python library for WiFi adapters. Communicates with the driver/kernel/OS directly.
Python
3
star
19

UnofficialDDNSnix

An unofficial dynamic DNS (DDNS) service for Name.com domains.
Python
3
star
20

Flask-JIRA-Helper

JIRA support for Flask without breaking PyCharm inspections.
Python
3
star
21

tape_bulk_eject

Eject multiple tapes from a Dell PowerVault 124T autoloader in one go.
Python
2
star
22

PythonTemplate

This is the template I use for my Python projects.
Python
2
star
23

robutils

Convenience classes for CLI Python applications.
Python
2
star
24

sphinx-imgur

Embed Imgur images and albums in Sphinx documents/pages.
Python
2
star
25

Flask-Statics-Helper

Provides Bootstrap3 and other static resources in a modular fashion.
JavaScript
2
star
26

general

General/misc scripts I use occasionally.
Python
1
star
27

qnx-neutrino-hello-world

Hello world for my MIB2 VW Infotainment System
1
star
28

jira-context

Cache JIRA basic authentication sessions to disk for console apps.
Python
1
star
29

gha_test

Test github actions
Makefile
1
star
30

GolangTemplate

This is the template I use for my Golang projects.
Makefile
1
star
31

githubBackup

Backups all of your GitHub public/private repos (with issues/wikis) and Gists.
Go
1
star
32

sphinx-carousel

A Sphinx extension for creating slideshows using Bootstrap Carousels.
Python
1
star