An example of a large scale Flask application using blueprints and extensions.
Quickly run the project using docker and docker-compose:
docker-compose up -d
Create the database and seed it with some data:
docker-compose run --rm app flask create-db
docker-compose run --rm app flask populate-db --num_users 5
Download front-end dependencies with yarn:
yarn install --modules-folder ./app/static/node_modules
The following environment variables are optional:
Name | Purpose |
---|---|
APP_NAME |
The name of the application. i.e Flask Bones |
MAIL_PORT |
The port number of an SMTP server. |
MAIL_SERVER |
The hostname of an SMTP server. |
MEMCACHED_HOST |
The hostname of a memcached server. |
MEMCACHED_PORT |
The port number of a memcached server. |
POSTGRES_HOST |
The hostname of a postgres database server. |
POSTGRES_PASS |
The password of a postgres database user. |
POSTGRES_PORT |
The port number of a postgres database server. |
POSTGRES_USER |
The name of a postgres database user. |
REDIS_HOST |
The hostname of a redis database server. |
REDIS_PORT |
The port number of a redis database server. |
SECRET_KEY |
A secret key required to provide authentication. |
SERVER_NAME |
The hostname and port number of the server. |
from app.extensions import cache
# Cache something
cache.set('some_key', 'some_value')
# Fetch it later
cache.get('some_key')
from app.extensions import mail
from flask_mail import Message
# Build an email
msg = Message('User Registration', sender='admin@flask-bones.com', recipients=[user.email])
msg.body = render_template('mail/registration.mail', user=user, token=token)
# Send
mail.send(msg)
RQ
is a simple job queue for python backed by
redis.
Define a job:
@rq.job
def send_email(msg):
mail.send(msg)
Start a worker:
flask rq worker
Queue the job for processing:
send_email.queue(msg)
Monitor the status of the queue:
flask rq info --interval 3
For help on all available commands:
flask rq --help
from app.extensions import login_user, logout_user, login_required
# Login user
login_user(user)
# You now have a global proxy for the user
current_user.is_authenticated
# Secure endpoints with a decorator
@login_required
# Log out user
logout_user()
from app.extensions import bcrypt
# Hash password
pw_hash = bcrypt.generate_password_hash('password')
# Validate password
bcrypt.check_password_hash(pw_hash, 'password')
from app.config import dev_config, test_config
app = Flask(__name__)
class dev_config():
DEBUG = True
class test_config():
TESTING = True
# Configure for testing
app.config.from_object(test_config)
# Configure for development
app.config.from_object(dev_config)
Place a csrf token on a form:
{{ form.csrf_token }}
Validate it:
form.validate_on_submit()
from app.extensions import limiter
@limiter.limit("5 per minute")
@auth.route('/login', methods=['GET', 'POST'])
def login():
# ...
return 'your_login_page_contents'
Run the test suite:
pytest
from app.user.models import User
# Fetch user by id
user = User.get_by_id(id)
# Save current state of user
user.update()
# Fetch a paginated set of users
users = User.query.paginate(page, 50)
Download front-end dependencies with yarn:
yarn install --modules-folder ./app/static/node_modules
Merge and compress them together with Flask-Assets:
flask assets build
Display the current revision:
flask db current
Create a new migration:
flask db revision
Upgrade the database to a later version:
flask db upgrade
Extract strings from source and compile a catalog (.pot
):
pybabel extract -F babel.cfg -o i18n/messages.pot .
Create a new resource (.po) for German translators:
pybabel init -i i18n/messages.pot -d i18n -l de
Compile translations (.mo):
pybabel compile -d i18n
Merge changes into resource files:
pybabel update -i i18n/messages.pot -d i18n