There are 5 chapter folders. CD into each one and follow the below Chapter outline.
- pip install requirements
pip install -r requirements.txt
-
(Optional) to work with a Heroku DB, create an application and attach PostgreSQL to the application. See chapters 2-5 in
task.py
and set the application name- You may use a local sqlLite DB instead of a Heroku deployed DB.
cd
into each chapter and run the invoke commands to start such as:
invoke start
invoke init-db
invoke seed-db
- Python uses
pip
as a package manager - Many data scientist use
conda
to install packages.
pip freeze > requirements.txt
pip install -r requirements.txt
app/__init__.py
- The main Flask application
- Application factory
- Allows for easier testing
app/config.py
- Place configs for Flask and its plugins here
export FLASK_APP="app:create_app('dev')"
export FLASK_ENV="development" &&
flask run
⚠️ DO NOT USE 'flask' cli for produciton
gunicorn --bind 0.0.0.0 --workers 2 "app:create_app('prod')"
- 0.0.0.0: An alias IP to say expose on all network interfaces.
- workers: number of unique web application processes to spin up.
- Check out Invoke
- Build pre-defined tasks with easy configuration for options
- see
./tasks.py
Example
invoke start
app/__init__.py
- Add SQLAlchemy INIT
- Add route to get users
app/models/user.py
- Create a model for the user table
app/config.py
- Add the SQLALCHEMY_DATABASE_URI config
app/tasks.py
- Add task to init db tables
- Add task to seed users
- run the seed on both local SQLite and PSQL
jsonify() doesn’t know how to convert a SQLAlchemy class to JSON.
If only there were a way to convert a serialized Python class into a deserialized dict. Then we could convert the dict with jsonify()…
In comes...![marshmallow](https://marshmallow.readthedocs.io/en/stable/_static/marshmallow-logo.png =200x200)
app/__init__.py
- The
/marsh
route uses a marshmallow Schema to deserialize a Python class. - We can control what’s being deserialized with the different Schemas. (UserSchema vs UserSchemaWithPassword)
- Marshmallow can also serialize and validate a dict with .load()
- e.g. an ISO date time stamp can be converted to a datetime object easily
app/config.py
- Add the proper configs: JWT_ACCESS_LIFESPAN JWT_REFRESH_LIFESPAN
app/__init__.py
- INIT Praetorian()
- Add login() route
- Protect routes with @auth_required decorator
tasks.py
- Use utils for password hashing
app/__init__.py
- INIT Flask Rest Plus
- Define prefix for all routes
- Convert routes to Flask Rest Plus
- Add Namespaces for segmenting API routes within swagger
- Define authorizations section to easily add a JWT header to requests
Open up Swagger docs!
app/schemas/user.py
- Add UserLoginSchema
app/__init__.py
- Flask_accepts allows for easy Marshmallow schema conversion to JSON as well as adding Schema to Swagger docs
- Decorate endpoints with @accepts & @responds