flask-bones
An example of a large scale Flask application using blueprints and extensions.
Setup
Quickly run the project using docker and docker-compose :
- ``` shell
- docker-compose up -d
- ```
Create the database and seed it with some data:
- ``` shell
- 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 :
- ``` shell
- yarn install --modules-folder ./app/static/node_modules
- ```
Configuration
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. |
Features
Caching with Memcached
- ``` python
- from app.extensions import cache
- # Cache something
- cache.set('some_key', 'some_value')
- # Fetch it later
- cache.get('some_key')
- ```
Email delivery
- ``` python
- 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)
- ```
Asynchronous job scheduling with RQ
RQ is a simple job queue for python backed by redis.
Define a job:
- ``` python
- @rq.job
- def send_email(msg):
- mail.send(msg)
- ```
Start a worker:
- ``` shell
- flask rq worker
- ```
Queue the job for processing:
- ``` python
- send_email.queue(msg)
- ```
Monitor the status of the queue:
- ``` shell
- flask rq info --interval 3
- ```
For help on all available commands:
- ``` shell
- flask rq --help
- ```
Stupid simple user management
- ``` python
- 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()
- ```
Password security that can keep up with Moores Law
- ``` python
- from app.extensions import bcrypt
- # Hash password
- pw_hash = bcrypt.generate_password_hash('password')
- # Validate password
- bcrypt.check_password_hash(pw_hash, 'password')
- ```
Easily swap between multiple application configurations
- ``` python
- 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)
- ```
Form validation & CSRF protection with WTForms
Place a csrf token on a form:
- ``` html
- {{ form.csrf_token }}
- ```
Validate it:
- ``` python
- form.validate_on_submit()
- ```
Rate-limit routes
- ``` python
- from app.extensions import limiter
- @limiter.limit("5 per minute")
- @auth.route('/login', methods=['GET', 'POST'])
- def login():
- # ...
- return 'your_login_page_contents'
- ```
Automated tests
Run the test suite:
- ``` shell
- pytest
- ```
Use any relational database using the SQLAlchemy ORM
- ``` python
- 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)
- ```
Front-end asset management
Download front-end dependencies with yarn :
- ``` shell
- yarn install --modules-folder ./app/static/node_modules
- ```
Merge and compress them together with Flask-Assets :
- ``` shell
- flask assets build
- ```
Version your database schema
Display the current revision:
- ``` shell
- flask db current
- ```
Create a new migration:
- ``` shell
- flask db revision
- ```
Upgrade the database to a later version:
- ``` shell
- flask db upgrade
- ```
Internationalize the application for other languages (i18n)
Extract strings from source and compile a catalog (.pot ):
- ``` shell
- pybabel extract -F babel.cfg -o i18n/messages.pot .
- ```
Create a new resource (.po) for German translators:
- ``` shell
- pybabel init -i i18n/messages.pot -d i18n -l de
- ```
Compile translations (.mo):
- ``` shell
- pybabel compile -d i18n
- ```
Merge changes into resource files:
- ``` shell
- pybabel update -i i18n/messages.pot -d i18n
- ```