Boilerplate template for a Python Flask application with Login, Admin and MongoDB. Do you want to start with Flask?

This is a boilerplate you can use with Flask-mongoengine, Flask-WTF and others. This will get your Flask app up and running.

Flask

Directory structure

Becaus Flask is a microframework it lets you decide on a lot of things. The structure of the Flask code is a personal view (or company view).

The directory structure that I recommend is:

├── README.md
├── application
│   ├── __init__.py
│   ├── controllers
│   │   └── __init__.py
│   ├── forms
│   │   └── __init__.py
│   ├── models
│   │   └── __init__.py
│   ├── services
│   │   └── __init__.py
│   ├── static
│   │   └── __init__.py
│   ├── templates
│   │   └── __init__.py
│   └── utils
│       └── __init__.py
├── config
│   ├── __init__.py
│   ├── default.py
│   ├── development.py
│   ├── development_sample.py
│   ├── production.py
│   ├── production_sample.py
│   └── testing.py
├── deploy
│   ├── flask_env.sh
│   ├── gunicorn.conf
│   ├── nginx.conf
│   └── supervisor.conf
├── manage.py
├── pylintrc
├── requirements.txt
├── tests
│   └── __init__.py
└── wsgi.py

A brief introduction here:

  • application: All logical codes for a project are placed here
  • config: the configuration file for the project
  • deploy: deployment related files
  • tests: the directory file in which the unit test code is located:
  • manage.py: Flask-Script run file
  • pylintrc: pylint standard
  • requirements.txt list of project dependent libraries
  • wsgi.py:wsgi run

This is the contents of requirements.txt file:

Flask==0.10.1
flask-mongoengine==0.7.5
Flask-Login==0.3.2
Flask-Admin==1.4.0
Flask-Redis==0.1.0
Flask-WTF==0.12

Boilerplate

So where to put the code?

  • Place the route code in application/controllers
  • place the model code in application/models.
  • Put the code of the initialization binding app in application/init.py.
  • Put the database in the config/development.py file.

Finally, the manager.py file is written. A few important files are outlined here.

File manager.py

# coding: utf-8
from flask.ext.script import Manager
from application import create_app
# Used by app debug & livereload
PORT = 8080
app = create_app()
manager = Manager(app)
@manager.command
def run():
    """Run app."""
    app.run(port=PORT)
if __name__ == "__main__":
    manager.run()

application/init.py

# coding: utf-8
import sys
import os
# Insert project root path to sys.path
project_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
if project_path not in sys.path:
    sys.path.insert(0, project_path)
import logging
from flask import Flask
from flask_wtf.csrf import CsrfProtect
from config import load_config
from application.extensions import db, login_manager
from application.models import User
from application.controllers import user_bp
# convert python's encoding to utf8
try:
    reload(sys)
    sys.setdefaultencoding('utf8')
except (AttributeError, NameError):
    pass
def create_app():
    """Create Flask app."""
    config = load_config()
    print config
    app = Flask(__name__)
    app.config.from_object(config)
    if not hasattr(app, 'production'):
        app.production = not app.debug and not app.testing
    # CSRF protect
    CsrfProtect(app)
    if app.debug or app.testing:
        # Log errors to stderr in production mode
        app.logger.addHandler(logging.StreamHandler())
        app.logger.setLevel(logging.ERROR)
    # Register components
    register_extensions(app)
    register_blueprint(app)
    return app
def register_extensions(app):
    """Register models."""
    db.init_app(app)
    login_manager.init_app(app)
    login_manager.login_view = 'login'
    @login_manager.user_loader
    def load_user(user_id):
        return User.objects(id=user_id).first()
def register_blueprint(app):
    app.register_blueprint(user_bp)

application/controllers/init.py

#!/usr/bin/env python
# encoding: utf-8
import json
from flask import Blueprint, request, jsonify
from flask.ext.login import current_user, login_user, logout_user
from application.models import User
user_bp = Blueprint('user', __name__, url_prefix='')
@user_bp.route('/login', methods=['POST'])
def login():
    info = json.loads(request.data)
    username = info.get('username', 'guest')
    password = info.get('password', '')
    user = User.objects(name=username,
                        password=password).first()
    if user:
        login_user(user)
        return jsonify(user.to_json())
    else:
        return jsonify({"status": 401,
                        "reason": "Username or Password Error"})
@user_bp.route('/logout', methods=['POST'])
def logout():
    logout_user()
    return jsonify(**{'result': 200,
                      'data': {'message': 'logout success'}})
@user_bp.route('/user_info', methods=['POST'])
def user_info():
    if current_user.is_authenticated:
        resp = {"result": 200,
                "data": current_user.to_json()}
    else:
        resp = {"result": 401,
                "data": {"message": "user no login"}}
    return jsonify(**resp)

config/development.py

# coding: utf-8
import os
class DevelopmentConfig(object):
    """Base config class."""
    # Flask app config
    DEBUG = False
    TESTING = False
    SECRET_KEY = "your_key"
    # Root path of project
    PROJECT_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
    # Site domain
    SITE_TITLE = "title"
    SITE_DOMAIN = "http://localhost:8080"
    # MongoEngine config
    MONGODB_SETTINGS = {
        'db': 'your_database',
        'host': 'localhost',
        'port': 27017
    }