Flask is a lightweight Web framework that we all know is more flexible, lightweight, secure and easy to use than other frameworks of the same type. Developers are free to write their own project structure, and there are plenty of third-party libraries to choose from. However, this flexibility also brings its own problems, such as for many beginners, the construction of the project structure is messy, difficult to maintain, and the classic import loop problems

Circular import problem

Many beginners like to write startup files and multiple routes in the same file, such as the following code:

As the number of view functions increases, the code becomes less and less maintainable. So it is necessary to split the view function. We split it into two files: Py and view.py, where run.py is used as the startup file of the program. The core object needs to be imported in view.py because routes are registered to the flask core object, and the View needs to be imported in run.py.

run.py

# coding: utf-8
__author__ = 'Jerry'

from flask import Flask

app = Flask(__name__)

from app.web import view


@app.route("/")
def index(a):
    return 'Hello World'


if __name__ == '__main__':
    app.run()
Copy the code

view.py

# coding: utf-8
__author__ = 'Jerry'
from flask import request

from run import app

@app.route("/add")
def add(a):
    name = request.args.get("name")
    return f"Add {name}"

@app.route("/delete")
def delete(a):
    name = request.args.get("name")
    return f"Delete {name}"

@app.route("/change",methods=["POST"])
def change(a):
    num = request.json
    return f"change {num}"
Copy the code

But when I start the program, enter the address http://127.0.0.1:5000/add? in your browser Name =Jerry, 404 Not Found

127.0.0.1:5000/ responds properly!

Why is that? Why can’t the view function registered in view.py be found? The reason is that because of the circular import, we import the view in run.py, and we import the app in run.py in view.py! What is the final result? Let’s find out through debugging!

Detail loop import

  • Start run, instantiate a Flask core object app for the first time, and import the View code. This is the first key point 1!

  • In view.py, execute the code that imported the app and execute the code in run.py instead

  • You can see that the program executes the code in run.py again, and again instantiates a Flask core object, called App2 for the sake of differentiation, which is the second key point 2!

As a result, __name __! = __ main __, so app.run() is not executed. The program will continue to execute the rest of the view.py code

As you can see, the application registered the associated routing function with App2! When the execution of the code in view.py is complete, the subsequent code in run.py is continued. This is the relevant code after key point 1 mentioned earlier!

__name __ == __ main __, so app.run() is successfully started!

Through the above analysis, the conclusion is as follows:

  • The entire process initializes the Flask core object, app, and App2 twice
  • View functions in view are registered with App2
  • The index view function was registered twice, first to app2 and last to app
  • The core object that eventually launches is app

By now you can see that the view function in view.py registers with a different app than the one that eventually launches, so the view function can’t be found! In order to have a more intuitive feeling, we can print the memory address of the APP, so that it is more clear at a glance!

The blueprint

Flask provides us with a mechanism, the Blueprint. A blueprint is a container that stores operation route mapping methods and is used to associate client requests with urls. Blueprints are similar to Django apps in that they are very similar in functionality and help us implement modular applications.

In Flask, you can create multiple blueprints, representing different functional modules. For example, the Web folder in the code above can serve as a blueprint, and the user-specific function module User can also create a blueprint

To solve the problem

After understanding the relevant functions of the blueprint, we officially adopted the blueprint to solve the above problems.

  • Start by creating the blueprint in the web/__ init __.py file:
# coding: utf-8
__author__ = 'Jerry'
from flask import Blueprint

api = Blueprint('api', __name__)

from app.web import view

if __name__ == '__main__':
    pass
Copy the code
  • After the blueprint is created, import the corresponding blueprint in view.py and register the view function with the blueprint.
# coding: utf-8
__author__ = 'Jerry'
from flask import request

from . import api

print(F "Register app in view:{id(api)}")

@api.route("/add")
def add(a):
    name = request.args.get("name")
    return f"Add {name}"

@api.route("/delete")
def delete(a):
    name = request.args.get("name")
    return f"Delete {name}"

@api.route("/change", methods=["POST"])
def change(a):
    num = request.json
    return f"change {num}"
Copy the code
  • It is always clear that the related functionality in Flask plugins and view functions are eventually registered with the core object, so blueprints are also registered with the core object. At the same time, it should be understood that when the project has more functions and a lot of plug-ins, there will be a lot of code related to initialization of core objects and the registration of blueprints and third-party plug-ins. At this time, the code should also be separated.

So do the initialization of the core object in the app/__ init __.py file and register the blueprint with the core object. The code is as follows:

At the same time, remember to import the app core object in the startup file run.py, and modify the code as follows:

The verification results

After running, we verify the GET request either in the browser or in code

A POST request

Perfect!