So far we've got a simple app with a few routes, but its already starting to get a bit cluttered, so to make this app easier to maintain as it grows, let's start adopting a more modular organizational structure.
We'll move the app into a new directory and split the route definitions across multiple files.
Application Factory Pattern
First, let's implement the Flask "application factory pattern" where we define our application inside a function. Among other benefits, this can help us test the app later.
Create a new subdirectory in your repo called "webapp" with a file called "\_init\.py" and place the following contents inside:
# web_app/__init__.py
from flask import Flask
from web_app.routes.home_routes import home_routes
from web_app.routes.book_routes import book_routes
from web_app.routes.weather_routes import weather_routes
def create_app():
app = Flask(__name__)
app.register_blueprint(home_routes)
app.register_blueprint(book_routes)
app.register_blueprint(weather_routes)
return app
if __name__ == "__main__":
my_app = create_app()
my_app.run(debug=True)
Review the new "create_app" function and notice we are importing and referencing the routing functions from their own logically-related files.
NOTE: in the future, whenever we add more routing files, we'll need to import and register them in this way for our app to recognize them!
Route Blueprints
Let's now move the route definitions to their own logically-related files, just to be more organized.
We're using Flask Blueprints to store the route definitions in a way the app can recognize.
Inside the "web_app" directory, create a new subdirectory called "routes" with new files called "home_routes.py", "book_routes.py", and place the following contents inside, respectively:
# web_app/routes/home_routes.py
from flask import Blueprint, request #, render_template
home_routes = Blueprint("home_routes", __name__)
@home_routes.route("/")
@home_routes.route("/home")
def index():
print("HOME...")
return "Welcome Home"
@home_routes.route("/about")
def about():
print("ABOUT...")
return "About Me"
@home_routes.route("/hello")
def hello_world():
print("HELLO...", dict(request.args))
# NOTE: `request.args` is dict-like, so below we're using the dictionary's `get()` method,
# ... which will return None instead of throwing an error if key is not present
# ... see also: https://www.w3schools.com/python/ref_dictionary_get.asp
name = request.args.get("name") or "World"
return f"Hello, {name}!"
Since we moved the Flask app into the "web_app" directory, we'll use this new command to run it moving forward:
# mac:
FLASK_APP=web_app flask run
# windows:
export FLASK_APP=web_app
flask run
Remember, the "init" file is the entry-point into a local Python module, so when we run the app this way, Flask will run the "web_app" module's "init" file.
Let's restart the web server using this new command, and visit the same URLs in the browser to see the app is working like it was before.
Great! With the modular codebase we'll be able to maintain and extend our app more easily in the future.